[2/11] ntdll/tests: Add tests for threadpool group cancel callback.
Sebastian Lackner
sebastian at fds-team.de
Wed Jul 1 15:53:09 CDT 2015
---
dlls/ntdll/tests/threadpool.c | 116 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 116 insertions(+)
diff --git a/dlls/ntdll/tests/threadpool.c b/dlls/ntdll/tests/threadpool.c
index b261cd1..2d64471 100644
--- a/dlls/ntdll/tests/threadpool.c
+++ b/dlls/ntdll/tests/threadpool.c
@@ -307,6 +307,121 @@ static void test_tp_work_scheduler(void)
pTpReleasePool(pool);
}
+static DWORD group_cancel_tid;
+
+static void CALLBACK group_cancel_cb(TP_CALLBACK_INSTANCE *instance, void *userdata)
+{
+ HANDLE *semaphores = userdata;
+ DWORD result;
+ trace("Running group cancel callback\n");
+ result = WaitForSingleObject(semaphores[0], 1000);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ReleaseSemaphore(semaphores[1], 1, NULL);
+}
+
+static void CALLBACK group_cancel_cleanup_release_cb(void *object, void *userdata)
+{
+ HANDLE *semaphores = userdata;
+ trace("Running group cancel cleanup release callback\n");
+ group_cancel_tid = GetCurrentThreadId();
+ ReleaseSemaphore(semaphores[0], 1, NULL);
+}
+
+static void CALLBACK group_cancel_cleanup_increment_cb(void *object, void *userdata)
+{
+ trace("Running group cancel cleanup increment callback\n");
+ group_cancel_tid = GetCurrentThreadId();
+ InterlockedIncrement((LONG *)userdata);
+}
+
+static void CALLBACK unexpected_cb(TP_CALLBACK_INSTANCE *instance, void *userdata)
+{
+ ok(0, "Unexpected callback\n");
+}
+
+static void test_tp_group_cancel(void)
+{
+ TP_CALLBACK_ENVIRON environment;
+ TP_CLEANUP_GROUP *group;
+ LONG userdata, userdata2;
+ HANDLE semaphores[2];
+ NTSTATUS status;
+ TP_WORK *work;
+ TP_POOL *pool;
+ DWORD result;
+ int i;
+
+ semaphores[0] = CreateSemaphoreA(NULL, 0, 1, NULL);
+ ok(semaphores[0] != NULL, "CreateSemaphoreA failed %u\n", GetLastError());
+ semaphores[1] = CreateSemaphoreA(NULL, 0, 1, NULL);
+ ok(semaphores[1] != NULL, "CreateSemaphoreA failed %u\n", GetLastError());
+
+ /* allocate new threadpool with only one thread */
+ pool = NULL;
+ status = pTpAllocPool(&pool, NULL);
+ ok(!status, "TpAllocPool failed with status %x\n", status);
+ ok(pool != NULL, "expected pool != NULL\n");
+ pTpSetPoolMaxThreads(pool, 1);
+
+ /* 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");
+
+ /* test execution of cancellation callback */
+ memset(&environment, 0, sizeof(environment));
+ environment.Version = 1;
+ environment.Pool = pool;
+ status = pTpSimpleTryPost(group_cancel_cb, semaphores, &environment);
+ ok(!status, "TpSimpleTryPost failed with status %x\n", status);
+
+ memset(&environment, 0, sizeof(environment));
+ environment.Version = 1;
+ environment.Pool = pool;
+ environment.CleanupGroup = group;
+ environment.CleanupGroupCancelCallback = group_cancel_cleanup_release_cb;
+ status = pTpSimpleTryPost(unexpected_cb, NULL, &environment);
+ ok(!status, "TpSimpleTryPost failed with status %x\n", status);
+
+ group_cancel_tid = 0xdeadbeef;
+ pTpReleaseCleanupGroupMembers(group, TRUE, semaphores);
+ result = WaitForSingleObject(semaphores[1], 1000);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(group_cancel_tid == GetCurrentThreadId(), "expected tid %x, got %x\n",
+ GetCurrentThreadId(), group_cancel_tid);
+
+ /* test cancellation callback for objects with multiple instances */
+ work = NULL;
+ memset(&environment, 0, sizeof(environment));
+ environment.Version = 1;
+ environment.Pool = pool;
+ environment.CleanupGroup = group;
+ environment.CleanupGroupCancelCallback = group_cancel_cleanup_increment_cb;
+ status = pTpAllocWork(&work, work_cb, &userdata, &environment);
+ ok(!status, "TpAllocWork failed with status %x\n", status);
+ ok(work != NULL, "expected work != NULL\n");
+
+ /* post 10 identical work items at once */
+ userdata = userdata2 = 0;
+ for (i = 0; i < 10; i++)
+ pTpPostWork(work);
+
+ /* check if we get multiple cancellation callbacks */
+ group_cancel_tid = 0xdeadbeef;
+ pTpReleaseCleanupGroupMembers(group, TRUE, &userdata2);
+ ok(userdata <= 8, "expected userdata <= 8, got %u\n", userdata);
+ ok(userdata2 == 1, "expected only one cancellation callback, got %u\n", userdata2);
+ ok(group_cancel_tid == GetCurrentThreadId(), "expected tid %x, got %x\n",
+ GetCurrentThreadId(), group_cancel_tid);
+
+ /* cleanup */
+ pTpReleaseCleanupGroup(group);
+ pTpReleasePool(pool);
+ CloseHandle(semaphores[0]);
+ CloseHandle(semaphores[1]);
+}
+
START_TEST(threadpool)
{
if (!init_threadpool())
@@ -315,4 +430,5 @@ START_TEST(threadpool)
test_tp_simple();
test_tp_work();
test_tp_work_scheduler();
+ test_tp_group_cancel();
}
--
2.4.4
More information about the wine-patches
mailing list