Module: wine Branch: master Commit: 51447083920885defa679d88579e13f838a2494c URL: http://source.winehq.org/git/wine.git/?a=commit;h=51447083920885defa679d8857...
Author: Sebastian Lackner sebastian@fds-team.de Date: Sat Aug 20 21:22:54 2016 +0200
ntdll/tests: Add tests for releasing threadpool objects during TpReleaseCleanupGroupMembers.
Signed-off-by: Sebastian Lackner sebastian@fds-team.de Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/ntdll/tests/threadpool.c | 109 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 108 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/tests/threadpool.c b/dlls/ntdll/tests/threadpool.c index 9b4b522..7672d63 100644 --- a/dlls/ntdll/tests/threadpool.c +++ b/dlls/ntdll/tests/threadpool.c @@ -1,7 +1,7 @@ /* * Unit test suite for thread pool functions * - * Copyright 2015 Sebastian Lackner + * Copyright 2015-2016 Sebastian Lackner * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -705,6 +705,112 @@ static void test_tp_work_scheduler(void) pTpReleasePool(pool); }
+static void CALLBACK work_release_cb(TP_CALLBACK_INSTANCE *instance, void *userdata, TP_WORK *work) +{ + HANDLE semaphore = userdata; + trace("Running work release callback\n"); + ReleaseSemaphore(semaphore, 1, NULL); + Sleep(200); /* wait until main thread is in TpReleaseCleanupGroupMembers */ + pTpReleaseWork(work); +} + +static void CALLBACK timer_release_cb(TP_CALLBACK_INSTANCE *instance, void *userdata, TP_TIMER *timer) +{ + HANDLE semaphore = userdata; + trace("Running timer release callback\n"); + ReleaseSemaphore(semaphore, 1, NULL); + Sleep(200); /* wait until main thread is in TpReleaseCleanupGroupMembers */ + pTpReleaseTimer(timer); +} + +static void CALLBACK wait_release_cb(TP_CALLBACK_INSTANCE *instance, void *userdata, + TP_WAIT *wait, TP_WAIT_RESULT result) +{ + HANDLE semaphore = userdata; + trace("Running wait release callback\n"); + ReleaseSemaphore(semaphore, 1, NULL); + Sleep(200); /* wait until main thread is in TpReleaseCleanupGroupMembers */ + pTpReleaseWait(wait); +} + +static void test_tp_group_wait(void) +{ + TP_CALLBACK_ENVIRON environment; + TP_CLEANUP_GROUP *group; + LARGE_INTEGER when; + HANDLE semaphore; + NTSTATUS status; + TP_TIMER *timer; + TP_WAIT *wait; + TP_WORK *work; + TP_POOL *pool; + DWORD result; + + semaphore = CreateSemaphoreA(NULL, 0, 1, NULL); + ok(semaphore != NULL, "CreateSemaphoreA failed %u\n", GetLastError()); + + /* allocate new threadpool */ + pool = NULL; + status = pTpAllocPool(&pool, NULL); + ok(!status, "TpAllocPool failed with status %x\n", status); + ok(pool != NULL, "expected pool != NULL\n"); + + /* allocate a cleanup group */ + group = NULL; + status = pTpAllocCleanupGroup(&group); + ok(!status, "TpAllocCleanupGroup failed with status %x\n", status); + ok(group != NULL, "expected pool != NULL\n"); + + /* release work object during TpReleaseCleanupGroupMembers */ + work = NULL; + memset(&environment, 0, sizeof(environment)); + environment.Version = 1; + environment.Pool = pool; + environment.CleanupGroup = group; + status = pTpAllocWork(&work, work_release_cb, semaphore, &environment); + ok(!status, "TpAllocWork failed with status %x\n", status); + ok(work != NULL, "expected work != NULL\n"); + pTpPostWork(work); + result = WaitForSingleObject(semaphore, 1000); + ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result); + pTpReleaseCleanupGroupMembers(group, FALSE, NULL); + + /* release timer object during TpReleaseCleanupGroupMembers */ + timer = NULL; + memset(&environment, 0, sizeof(environment)); + environment.Version = 1; + environment.Pool = pool; + environment.CleanupGroup = group; + status = pTpAllocTimer(&timer, timer_release_cb, semaphore, &environment); + ok(!status, "TpAllocTimer failed with status %x\n", status); + ok(timer != NULL, "expected timer != NULL\n"); + when.QuadPart = 0; + pTpSetTimer(timer, &when, 0, 0); + result = WaitForSingleObject(semaphore, 1000); + ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result); + pTpReleaseCleanupGroupMembers(group, FALSE, NULL); + + /* release wait object during TpReleaseCleanupGroupMembers */ + wait = NULL; + memset(&environment, 0, sizeof(environment)); + environment.Version = 1; + environment.Pool = pool; + environment.CleanupGroup = group; + status = pTpAllocWait(&wait, wait_release_cb, semaphore, &environment); + ok(!status, "TpAllocWait failed with status %x\n", status); + ok(wait != NULL, "expected wait != NULL\n"); + when.QuadPart = 0; + pTpSetWait(wait, INVALID_HANDLE_VALUE, &when); + result = WaitForSingleObject(semaphore, 1000); + ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result); + pTpReleaseCleanupGroupMembers(group, FALSE, NULL); + + /* cleanup */ + pTpReleaseCleanupGroup(group); + pTpReleasePool(pool); + CloseHandle(semaphore); +} + static DWORD group_cancel_tid;
static void CALLBACK group_cancel_cb(TP_CALLBACK_INSTANCE *instance, void *userdata) @@ -1679,6 +1785,7 @@ START_TEST(threadpool) test_tp_simple(); test_tp_work(); test_tp_work_scheduler(); + test_tp_group_wait(); test_tp_group_cancel(); test_tp_instance(); test_tp_disassociate();