aboutsummaryrefslogtreecommitdiff
path: root/tests/libutil
diff options
context:
space:
mode:
Diffstat (limited to 'tests/libutil')
-rw-r--r--tests/libutil/Makemodule.am6
-rw-r--r--tests/libutil/threadpool.c111
2 files changed, 116 insertions, 1 deletions
diff --git a/tests/libutil/Makemodule.am b/tests/libutil/Makemodule.am
index 1153db4..1fe4ebf 100644
--- a/tests/libutil/Makemodule.am
+++ b/tests/libutil/Makemodule.am
@@ -8,8 +8,12 @@ test_rbtree_LDADD = libutil.a libcompat.a
test_xxhash_SOURCES = tests/libutil/xxhash.c
test_xxhash_LDADD = libutil.a libcompat.a
+test_threadpool_SOURCES = tests/libutil/threadpool.c
+test_threadpool_CFLAGS = $(AM_CFLAGS) $(PTHREAD_CFLAGS)
+test_threadpool_LDADD = libutil.a libcompat.a $(PTHREAD_LIBS)
+
LIBUTIL_TESTS = \
- test_str_table test_rbtree test_xxhash
+ test_str_table test_rbtree test_xxhash test_threadpool
check_PROGRAMS += $(LIBUTIL_TESTS)
TESTS += $(LIBUTIL_TESTS)
diff --git a/tests/libutil/threadpool.c b/tests/libutil/threadpool.c
new file mode 100644
index 0000000..566239f
--- /dev/null
+++ b/tests/libutil/threadpool.c
@@ -0,0 +1,111 @@
+/* SPDX-License-Identifier: LGPL-3.0-or-later */
+/*
+ * threadpool.c
+ *
+ * Copyright (C) 2021 David Oberhollenzer <goliath@infraroot.at>
+ */
+#include "config.h"
+
+#include "threadpool.h"
+#include "../test.h"
+
+#if defined(_WIN32) || defined(__WINDOWS__)
+#define WIN32_LEAN_AND_MEAN
+#define VC_EXTRALEAN
+#include <windows.h>
+#endif
+
+#include <time.h>
+
+static int worker(void *user, void *work_item)
+{
+ unsigned int value = *((unsigned int *)work_item);
+ (void)user;
+
+#if defined(_WIN32) || defined(__WINDOWS__)
+ Sleep(100 * value);
+#else
+ {
+ struct timespec sp;
+
+ sp.tv_sec = value / 10;
+ sp.tv_nsec = 100000000;
+ sp.tv_nsec *= (long)(value % 10);
+
+ nanosleep(&sp, NULL);
+ }
+#endif
+
+ *((unsigned int *)work_item) = 42;
+ return 0;
+}
+
+int main(void)
+{
+ unsigned int values[10];
+ thread_pool_t *pool;
+ unsigned int *ptr;
+ size_t i, count;
+ int ret;
+
+ pool = thread_pool_create(10, worker);
+ TEST_NOT_NULL(pool);
+
+ count = pool->get_worker_count(pool);
+ TEST_ASSERT(count >= 1);
+
+ /* dequeue on empty pool MUST NOT deadlock */
+ ptr = pool->dequeue(pool);
+ TEST_NULL(ptr);
+
+ for (i = 0; i < sizeof(values) / sizeof(values[0]); ++i) {
+ values[i] = sizeof(values) / sizeof(values[0]) - i;
+
+ ret = pool->submit(pool, values + i);
+ TEST_EQUAL_I(ret, 0);
+ }
+
+ for (i = 0; i < sizeof(values) / sizeof(values[0]); ++i) {
+ ptr = pool->dequeue(pool);
+
+ TEST_NOT_NULL(ptr);
+ TEST_ASSERT(ptr == (values + i));
+ TEST_EQUAL_UI(*ptr, 42);
+ }
+
+ ptr = pool->dequeue(pool);
+ TEST_NULL(ptr);
+
+ pool->destroy(pool);
+
+ /* redo the same test with the serial implementation */
+ pool = thread_pool_create_serial(worker);
+ TEST_NOT_NULL(pool);
+
+ ptr = pool->dequeue(pool);
+ TEST_NULL(ptr);
+
+ count = pool->get_worker_count(pool);
+ TEST_EQUAL_UI(count, 1);
+
+ for (i = 0; i < sizeof(values) / sizeof(values[0]); ++i) {
+ values[i] = sizeof(values) / sizeof(values[0]) - i;
+
+ ret = pool->submit(pool, values + i);
+ TEST_EQUAL_I(ret, 0);
+ }
+
+ for (i = 0; i < sizeof(values) / sizeof(values[0]); ++i) {
+ ptr = pool->dequeue(pool);
+
+ TEST_NOT_NULL(ptr);
+ TEST_ASSERT(ptr == (values + i));
+ TEST_EQUAL_UI(*ptr, 42);
+ }
+
+ ptr = pool->dequeue(pool);
+ TEST_NULL(ptr);
+
+ pool->destroy(pool);
+ return EXIT_SUCCESS;
+}