summaryrefslogtreecommitdiff
path: root/tests/test_threadpool.c
diff options
context:
space:
mode:
authorMark Michelson <mmichelson@digium.com>2012-12-09 18:56:25 +0000
committerMark Michelson <mmichelson@digium.com>2012-12-09 18:56:25 +0000
commit293b18ecce9ef4c0d6540fdd7cf324dd1cab9e38 (patch)
tree835c102200c705f106b5dd39779990c36ed09007 /tests/test_threadpool.c
parent75559a4c429db8e41d59a4ac6bd4a4757a530b2f (diff)
Create longer thread destruction test.
This one involves shrinking the threadpool in such a way that both idle and active threads are affected. This test made me re-realize why the zombie state exists, so I re-added it. We don't want to clog up the control taskprocessor by waiting on active threads to complete what they are doing. Instead, we mark them as zombies so that when they are done, they can clean themselves up properly. Without the zombie state available, the new test actually will deadlock. git-svn-id: https://origsvn.digium.com/svn/asterisk/team/mmichelson/threadpool@377474 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'tests/test_threadpool.c')
-rw-r--r--tests/test_threadpool.c94
1 files changed, 94 insertions, 0 deletions
diff --git a/tests/test_threadpool.c b/tests/test_threadpool.c
index 3435b2877..3d64fe914 100644
--- a/tests/test_threadpool.c
+++ b/tests/test_threadpool.c
@@ -842,6 +842,98 @@ end:
return res;
}
+AST_TEST_DEFINE(threadpool_more_destruction)
+{
+ struct ast_threadpool *pool = NULL;
+ struct ast_threadpool_listener *listener = NULL;
+ struct complex_task_data *ctd1 = NULL;
+ struct complex_task_data *ctd2 = NULL;
+ enum ast_test_result_state res = AST_TEST_FAIL;
+ struct test_listener_data *tld;
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "threadpool_more_destruction";
+ info->category = "/main/threadpool/";
+ info->summary = "Test that threads are destroyed as expected";
+ info->description =
+ "Push two tasks into a threadpool. Set the threadpool size to 4\n"
+ "Ensure that there are 2 active and 2 idle threads. Then shrink the\n"
+ "threadpool down to 1 thread. Ensure that the thread leftove is active\n"
+ "and ensure that both tasks complete.\n";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ listener = ast_threadpool_listener_alloc(&test_callbacks);
+ if (!listener) {
+ return AST_TEST_FAIL;
+ }
+ tld = listener->private_data;
+
+ pool = ast_threadpool_create(listener, 0);
+ if (!pool) {
+ goto end;
+ }
+
+ ctd1 = complex_task_data_alloc();
+ ctd2 = complex_task_data_alloc();
+ if (!ctd1 || !ctd2) {
+ goto end;
+ }
+
+ ast_threadpool_push(pool, complex_task, ctd1);
+ ast_threadpool_push(pool, complex_task, ctd2);
+
+ ast_threadpool_set_size(pool, 4);
+
+ WAIT_WHILE(tld, tld->num_idle < 2);
+
+ res = listener_check(test, listener, 1, 0, 2, 2, 2, 0);
+ if (res == AST_TEST_FAIL) {
+ goto end;
+ }
+
+ ast_threadpool_set_size(pool, 1);
+
+ /* Shrinking the threadpool should kill off the two idle threads
+ * and one of the active threads.
+ */
+ WAIT_WHILE(tld, tld->num_idle > 0 || tld->num_active > 1);
+
+ res = listener_check(test, listener, 1, 0, 2, 1, 0, 0);
+ if (res == AST_TEST_FAIL) {
+ goto end;
+ }
+
+ /* The tasks are stalled until we poke them */
+ poke_worker(ctd1);
+ poke_worker(ctd2);
+
+ res = wait_for_complex_completion(ctd1);
+ if (res == AST_TEST_FAIL) {
+ goto end;
+ }
+ res = wait_for_complex_completion(ctd2);
+ if (res == AST_TEST_FAIL) {
+ goto end;
+ }
+
+ WAIT_WHILE(tld, tld->num_idle < 1);
+
+ res = listener_check(test, listener, 1, 0, 2, 0, 1, 1);
+
+end:
+ if (pool) {
+ ast_threadpool_shutdown(pool);
+ }
+ ao2_cleanup(listener);
+ ast_free(ctd1);
+ ast_free(ctd2);
+ return res;
+}
+
static int unload_module(void)
{
ast_test_unregister(threadpool_push);
@@ -852,6 +944,7 @@ static int unload_module(void)
ast_test_unregister(threadpool_one_thread_multiple_tasks);
ast_test_unregister(threadpool_reactivation);
ast_test_unregister(threadpool_task_distribution);
+ ast_test_unregister(threadpool_more_destruction);
return 0;
}
@@ -865,6 +958,7 @@ static int load_module(void)
ast_test_register(threadpool_one_thread_multiple_tasks);
ast_test_register(threadpool_reactivation);
ast_test_register(threadpool_task_distribution);
+ ast_test_register(threadpool_more_destruction);
return AST_MODULE_LOAD_SUCCESS;
}