diff options
Diffstat (limited to 'tests/libutil')
-rw-r--r-- | tests/libutil/Makemodule.am | 6 | ||||
-rw-r--r-- | tests/libutil/threadpool.c | 111 |
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; +} |