diff options
Diffstat (limited to 'tests')
| -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; +} | 
