[TESTS] added test_pools from Aleksandar Lazic

This simple test performs memory allocations using pools and
mallocs and returns the average number of allocations per second.
diff --git a/tests/test_pools.c b/tests/test_pools.c
new file mode 100644
index 0000000..9ef833c
--- /dev/null
+++ b/tests/test_pools.c
@@ -0,0 +1,184 @@
+/*
+ * Contribution from Aleksandar Lazic <al-haproxy@none.at>
+ *
+ * Build with :  gcc -O2 -o test_pools test_pools.c
+ */
+
+#include <sys/time.h>
+#include <time.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <stdio.h>
+
+static struct timeval timeval_current(void)
+{
+	struct timeval tv;
+	gettimeofday(&tv, NULL);
+	return tv;
+}
+
+static double timeval_elapsed(struct timeval *tv)
+{
+	struct timeval tv2 = timeval_current();
+	return (tv2.tv_sec - tv->tv_sec) + 
+	       (tv2.tv_usec - tv->tv_usec)*1.0e-6;
+}
+
+#define torture_assert(test, expr, str) if (!(expr)) { \
+	printf("failure: %s [\n%s: Expression %s failed: %s\n]\n", \
+		test, __location__, #expr, str); \
+	return false; \
+}
+
+#define torture_assert_str_equal(test, arg1, arg2, desc) \
+	if (strcmp(arg1, arg2)) { \
+		printf("failure: %s [\n%s: Expected %s, got %s: %s\n]\n", \
+		   test, __location__, arg1, arg2, desc); \
+		return false; \
+	}
+
+/* added pools from haproxy */
+#include <stdlib.h>
+
+/*
+ * Returns a pointer to an area of <__len> bytes taken from the pool <pool> or
+ * dynamically allocated. In the first case, <__pool> is updated to point to
+ * the next element in the list.
+ */
+#define pool_alloc_from(__pool, __len)                      \
+({                                                          \
+        void *__p;                                          \
+        if ((__p = (__pool)) == NULL)                       \
+                __p = malloc(((__len) >= sizeof (void *)) ? \
+                      (__len) : sizeof(void *));            \
+        else {                                              \
+                __pool = *(void **)(__pool);                \
+        }                                                   \
+        __p;                                                \
+})
+
+/*
+ * Puts a memory area back to the corresponding pool.
+ * Items are chained directly through a pointer that
+ * is written in the beginning of the memory area, so
+ * there's no need for any carrier cell. This implies
+ * that each memory area is at least as big as one
+ * pointer.
+ */
+#define pool_free_to(__pool, __ptr)             \
+({                                              \
+        *(void **)(__ptr) = (void *)(__pool);   \
+        __pool = (void *)(__ptr);               \
+})
+
+/*
+ * Returns a pointer to type <type> taken from the
+ * pool <pool_type> or dynamically allocated. In the
+ * first case, <pool_type> is updated to point to the
+ * next element in the list.
+ */
+#define pool_alloc(type)                                \
+({                                                      \
+        void *__p;                                      \
+        if ((__p = pool_##type) == NULL)                \
+                __p = malloc(sizeof_##type);            \
+        else {                                          \
+                pool_##type = *(void **)pool_##type;	\
+        }                                               \
+        __p;                                            \
+})
+
+/*
+ * Puts a memory area back to the corresponding pool.
+ * Items are chained directly through a pointer that
+ * is written in the beginning of the memory area, so
+ * there's no need for any carrier cell. This implies
+ * that each memory area is at least as big as one
+ * pointer.
+ */
+#define pool_free(type, ptr)                            \
+({                                                      \
+        *(void **)ptr = (void *)pool_##type;            \
+        pool_##type = (void *)ptr;                      \
+})
+
+/*
+ * This function destroys a pull by freeing it completely.
+ * This should be called only under extreme circumstances.
+ */
+static inline void pool_destroy(void **pool)
+{
+	void *temp, *next;
+	next = pool;
+	while (next) {
+		temp = next;
+		next = *(void **)temp;
+		free(temp);
+	}
+}
+
+#define sizeof_talloc   1000
+
+/*
+  measure the speed of hapx versus malloc
+*/
+static bool test_speed1(void)
+{
+        void **pool_talloc = NULL;
+	void *ctx = pool_alloc(talloc);
+	unsigned count;
+	const int loop = 1000;
+	int i;
+	struct timeval tv;
+
+	printf("test: speed [\nhaproxy-pool VS MALLOC SPEED 2\n]\n");
+
+	tv = timeval_current();
+	count = 0;
+	do {
+		void *p1, *p2, *p3;
+		for (i=0;i<loop;i++) {
+			p1 = pool_alloc_from(pool_talloc, 10 + loop % 100);
+			p2 = pool_alloc_from(pool_talloc, strlen("foo bar") + 1);
+			strcpy(p2, "foo bar");
+			p3 = pool_alloc_from(pool_talloc, 300);
+			pool_free_to(pool_talloc,p1);
+			pool_free_to(pool_talloc,p3);
+			pool_free_to(pool_talloc,p2);
+		}
+		count += 3 * loop;
+	} while (timeval_elapsed(&tv) < 5.0);
+
+	fprintf(stderr, "haprox: %.0f ops/sec\n", count/timeval_elapsed(&tv));
+
+        pool_destroy(pool_talloc);
+
+	tv = timeval_current();
+	count = 0;
+	do {
+		void *p1, *p2, *p3;
+		for (i=0;i<loop;i++) {
+			p1 = malloc(10 + loop % 100);
+			p2 = strdup("foo bar");
+			p3 = malloc(300);
+			free(p1);
+			free(p2);
+			free(p3);
+		}
+		count += 3 * loop;
+	} while (timeval_elapsed(&tv) < 5.0);
+	fprintf(stderr, "malloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
+
+	printf("success: speed1\n");
+
+	return true;
+}
+
+int main(void)
+{
+	bool ret = test_speed1();
+	if (!ret)
+		return -1;
+	return 0;
+}