---
 Makefile.test        |  21 +++++++++
 tests/test-queue.cfg |   8 ++++
 tests/test_queue.c   | 117
+++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 146 insertions(+)


diff --git a/Makefile.test b/Makefile.test
new file mode 100644
index 000000000..41dd03c71
--- /dev/null
+++ b/Makefile.test
@@ -0,0 +1,21 @@
+include Makefile
+
+tests/haproxy_test.c: src/haproxy.c
+	sed -e 's/^int main(/int __main(/' < $< > $@
+
+tests/test_queue.o: tests/test_queue.c $(DEP)
+	$(CC) $(COPTS) \
+	      -DBUILD_TARGET='"$(strip $(TARGET))"' \
+	      -DBUILD_ARCH='"$(strip $(ARCH))"' \
+	      -DBUILD_CPU='"$(strip $(CPU))"' \
+	      -DBUILD_CC='"$(strip $(CC))"' \
+	      -DBUILD_CFLAGS='"$(strip $(VERBOSE_CFLAGS))"' \
+	      -DBUILD_OPTIONS='"$(strip $(BUILD_OPTIONS))"' \
+	       -c -o $@ $<
+
+tests/test_queue: tests/test_queue.o $(OPTIONS_OBJS) $(EBTREE_OBJS) $(OBJS)
+	$(LD) $(LDFLAGS) -o $@ $(filter-out src/haproxy.o,$^) $(LDOPTS)
+
+.PHONY: test
+test: tests/test_queue
+	./tests/test_queue
diff --git a/tests/test-queue.cfg b/tests/test-queue.cfg
new file mode 100644
index 000000000..903cf22d0
--- /dev/null
+++ b/tests/test-queue.cfg
@@ -0,0 +1,8 @@
+defaults
+	timeout client 5s
+	timeout server 5s
+	timeout connect 5s
+
+listen l1
+	bind :8001
+	server s1 127.0.0.1:8888 maxconn 1
diff --git a/tests/test_queue.c b/tests/test_queue.c
new file mode 100644
index 000000000..a92bd0233
--- /dev/null
+++ b/tests/test_queue.c
@@ -0,0 +1,117 @@
+#include "haproxy_test.c"
+
+#include <proto/queue.h>
+#include <proto/server.h>
+#include <proto/proxy.h>
+#include <proto/session.h>
+#include <proto/stream.h>
+
+#include <stdio.h>
+
+// Usage:
+// make -f Makefile.test USE_THREAD=1 DEBUG=-DDEBUG_THREAD TARGET=XXX test
+
+#ifndef USE_THREAD
+#error USE_THREAD is not set (USE_THREAD=1)
+#endif
+#ifndef DEBUG_THREAD
+#error DEBUG_THREAD is not set (DEBUG=-DDEBUG_THREAD)
+#endif
+
+struct test_spec_pendconn {
+	int key;
+	int locked;
+};
+
+struct test_spec {
+	struct test_spec_pendconn pendconns[3];
+	int expected;
+};
+
+int main(void)
+{
+	int argc = 3;
+	char *argv[] = {"haproxy","-f","tests/test-queue.cfg"};
+	init(argc, argv);
+
+	struct proxy *px;
+	struct server *srv;
+	struct stream *strm;
+
+	for (px = proxies_list; px; px = px->next)
+		if (!strcmp(px->id, "l1"))
+			break;
+	srv = px->srv;
+
+	struct test_spec tests[] = {
+		/*  0                  1                  2                 */
+		/* [0123456789ABCDEF],[0123456789ABCDEF],[0123456789ABCDEF] */
+		/* [........|...*...],[........|.......],[........|.......] */ {{{0x0c}},0},
+		/* [...*....|.......],[........|.......],[........|.......] */ {{{0x03}},0},
+		/* [...*....|.......],[...*....|.......],[........|.......] */ {{{0x03},{0x13}},0},
+		/* [...*....|...*...],[........|.......],[........|.......] */ {{{0x03},{0x0c}},1},
+		/* [...*....|X..*...],[........|.......],[........|.......] */ {{{0x03},{0x09,1},{0x0c}},2},
+		/* [...*....|...X...],[........|.......],[........|.......] */ {{{0x03},{0x0c,1}},0},
+		/* [...*....|...X...],[...X....|.......],[........|.......] */ {{{0x03},{0x0c,1},{0x13,1}},0},
+		/* [........|...X...],[...X....|...*...],[........|.......] */ {{{0x0c,1},{0x13,1},{0x1c}},2},
+		/* [........|...X...],[...*....|...X...],[........|.......] */ {{{0x0c,1},{0x13},{0x1c,1}},1},
+		/* [........|...X...],[...*....|.......],[........|.......] */ {{{0x0c,1},{0x13}},1},
+		/* [........|...X...],[...*....|...*...],[........|.......] */ {{{0x0c,1},{0x13},{0x1c}},2},
+		/* [........|.......],[...*....|.......],[........|.......] */ {{{0x13}},0},
+		/* [........|.......],[...*....|...*...],[........|.......] */ {{{0x13},{0x1c}},1},
+		/* [........|.......],[........|...*...],[........|.......] */ {{{0x1c}},0},
+		/* [........|.......],[...*....|.......],[........|.......] */ {{{0x13}},0},
+		/* [........|...X...],[...*....|.......],[..*.....|.......] */ {{{0x0c,1},{0x13},{0x22}},1},
+		/* [........|...X...],[........|.......],[........|.......] */ {{{0x0c,1}},-1},
+		/* [........*...*...],[........|.......],[........|.......] */ {{{0x08},{0x0c}},0},
+		/* [...*....*.......],[........|.......],[........|.......] */ {{{0x03},{0x08}},1},
+		/* [........|.......],[...*....*.......],[........|.......] */ {{{0x13},{0x1c}},1},
+	};
+
+	now_ms = 0x00000;
+	struct eb32_node *node;
+	struct test_spec test;
+	for (int i = 0; i < sizeof(tests)/sizeof(tests[0]); i++ ) {
+		while ((node = eb32_first(&px->pendconns)))
+			eb32_delete(node);
+		srv->served = 0;
+
+		test = tests[i];
+		struct pendconn *pcs[sizeof(test.pendconns)/sizeof(test.pendconns[0])];
+
+		for (int j = 0; j < sizeof(test.pendconns)/sizeof(test.pendconns[0]); j++) {
+			if (!test.pendconns[j].key) {
+				pcs[j] = NULL;
+				break;
+			}
+
+			strm = stream_new(session_new(px, NULL, NULL), NULL);
+			strm->priority_class = (test.pendconns[j].key >> 4) - 0x7ff;
+			strm->priority_offset = (test.pendconns[j].key & 0xf) * 0x10000;
+			if (strm->priority_offset >= 0x80000)
+				strm->priority_offset -= 0x100000;
+
+			pcs[j] = pendconn_add(strm);
+
+			if (test.pendconns[j].locked) {
+				HA_SPIN_LOCK(PENDCONN_LOCK, &pcs[j]->lock);
+				pcs[j]->lock.info.owner <<= 1;
+			}
+		}
+
+		process_srv_queue(srv);
+		int actual = -1;
+		for (int j = 0; j < sizeof(test.pendconns)/sizeof(test.pendconns[0]); j++) {
+			if (pcs[j] == NULL)
+				break;
+			if (pcs[j]->srv == srv) {
+				actual = j;
+				break;
+			}
+		}
+		if (actual != test.expected)
+			printf("%d Failed. Expected=%d Actual=%d\n", i, test.expected, actual);
+		else
+			printf("%d Passed. Result=%d\n", i, actual);
+	}
+}

Reply via email to