[3/3] ntdll/tests: Add tests for RtlRegisterWait.
Sebastian Lackner
sebastian at fds-team.de
Tue Oct 6 18:24:50 CDT 2015
Signed-off-by: Sebastian Lackner <sebastian at fds-team.de>
---
dlls/ntdll/tests/threadpool.c | 253 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 253 insertions(+)
diff --git a/dlls/ntdll/tests/threadpool.c b/dlls/ntdll/tests/threadpool.c
index a262ecb..ec0a29c 100644
--- a/dlls/ntdll/tests/threadpool.c
+++ b/dlls/ntdll/tests/threadpool.c
@@ -143,6 +143,258 @@ static void test_RtlQueueWorkItem(void)
CloseHandle(semaphore);
}
+struct rtl_wait_info
+{
+ HANDLE semaphore1;
+ HANDLE semaphore2;
+ DWORD wait_result;
+ LONG userdata;
+};
+
+static void CALLBACK rtl_wait_cb(void *userdata, BOOLEAN timeout)
+{
+ struct rtl_wait_info *info = userdata;
+ DWORD result;
+
+ trace("Running rtl_wait callback\n");
+
+ if (!timeout)
+ InterlockedIncrement(&info->userdata);
+ else
+ InterlockedExchangeAdd(&info->userdata, 0x10000);
+ ReleaseSemaphore(info->semaphore1, 1, NULL);
+
+ if (info->semaphore2)
+ {
+ result = WaitForSingleObject(info->semaphore2, 200);
+ ok(result == info->wait_result, "expected %u, got %u\n", info->wait_result, result);
+ ReleaseSemaphore(info->semaphore1, 1, NULL);
+ }
+}
+
+static void test_RtlRegisterWait(void)
+{
+ struct rtl_wait_info info;
+ HANDLE semaphores[2];
+ NTSTATUS status;
+ DWORD result;
+ HANDLE wait1;
+ HANDLE event;
+
+ semaphores[0] = CreateSemaphoreW(NULL, 0, 2, NULL);
+ ok(semaphores[0] != NULL, "failed to create semaphore\n");
+ semaphores[1] = CreateSemaphoreW(NULL, 0, 1, NULL);
+ ok(semaphores[1] != NULL, "failed to create semaphore\n");
+ info.semaphore1 = semaphores[0];
+ info.semaphore2 = NULL;
+
+ event = CreateEventW(NULL, FALSE, FALSE, NULL);
+ ok(event != NULL, "failed to create event\n");
+
+ /* basic test for RtlRegisterWait and RtlDeregisterWait */
+ wait1 = NULL;
+ info.userdata = 0;
+ status = RtlRegisterWait(&wait1, semaphores[1], rtl_wait_cb, &info, INFINITE, WT_EXECUTEDEFAULT);
+ ok(!status, "RtlRegisterWait failed with status %x\n", status);
+ ok(wait1 != NULL, "expected wait1 != NULL\n");
+ status = RtlDeregisterWait(wait1);
+ ok(!status, "RtlDeregisterWait failed with status %x\n", status);
+ ok(info.userdata == 0, "expected info.userdata = 0, got %u\n", info.userdata);
+
+ /* infinite timeout, signal the semaphore two times */
+ info.userdata = 0;
+ status = RtlRegisterWait(&wait1, semaphores[1], rtl_wait_cb, &info, INFINITE, WT_EXECUTEDEFAULT);
+ ok(!status, "RtlRegisterWait failed with status %x\n", status);
+ ReleaseSemaphore(semaphores[1], 1, NULL);
+ result = WaitForSingleObject(semaphores[0], 100);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(info.userdata == 1, "expected info.userdata = 1, got %u\n", info.userdata);
+ ReleaseSemaphore(semaphores[1], 1, NULL);
+ result = WaitForSingleObject(semaphores[0], 100);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(info.userdata == 2, "expected info.userdata = 2, got %u\n", info.userdata);
+ result = WaitForSingleObject(semaphores[1], 0);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
+ status = RtlDeregisterWait(wait1);
+ ok(!status || broken(status == STATUS_PENDING) /* >= Win 8 */,
+ "RtlDeregisterWait failed with status %x\n", status);
+
+ /* repeat test with WT_EXECUTEONLYONCE */
+ info.userdata = 0;
+ status = RtlRegisterWait(&wait1, semaphores[1], rtl_wait_cb, &info, INFINITE, WT_EXECUTEONLYONCE);
+ ok(!status, "RtlRegisterWait failed with status %x\n", status);
+ ReleaseSemaphore(semaphores[1], 1, NULL);
+ result = WaitForSingleObject(semaphores[0], 100);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(info.userdata == 1, "expected info.userdata = 1, got %u\n", info.userdata);
+ ReleaseSemaphore(semaphores[1], 1, NULL);
+ result = WaitForSingleObject(semaphores[0], 100);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
+ ok(info.userdata == 1, "expected info.userdata = 1, got %u\n", info.userdata);
+ result = WaitForSingleObject(semaphores[1], 0);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ status = RtlDeregisterWait(wait1);
+ ok(!status, "RtlDeregisterWait failed with status %x\n", status);
+
+ /* finite timeout, no event */
+ info.userdata = 0;
+ status = RtlRegisterWait(&wait1, semaphores[1], rtl_wait_cb, &info, 200, WT_EXECUTEDEFAULT);
+ ok(!status, "RtlRegisterWait failed with status %x\n", status);
+ result = WaitForSingleObject(semaphores[0], 100);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
+ ok(info.userdata == 0, "expected info.userdata = 0, got %u\n", info.userdata);
+ result = WaitForSingleObject(semaphores[0], 200);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(info.userdata == 0x10000, "expected info.userdata = 0x10000, got %u\n", info.userdata);
+ result = WaitForSingleObject(semaphores[1], 0);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
+ status = RtlDeregisterWait(wait1);
+ ok(!status || broken(status == STATUS_PENDING) /* >= Win 8 */,
+ "RtlDeregisterWait failed with status %x\n", status);
+
+ /* finite timeout, with event */
+ info.userdata = 0;
+ status = RtlRegisterWait(&wait1, semaphores[1], rtl_wait_cb, &info, 200, WT_EXECUTEDEFAULT);
+ ok(!status, "RtlRegisterWait failed with status %x\n", status);
+ result = WaitForSingleObject(semaphores[0], 100);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
+ ok(info.userdata == 0, "expected info.userdata = 0, got %u\n", info.userdata);
+ ReleaseSemaphore(semaphores[1], 1, NULL);
+ result = WaitForSingleObject(semaphores[0], 100);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(info.userdata == 1, "expected info.userdata = 1, got %u\n", info.userdata);
+ result = WaitForSingleObject(semaphores[1], 0);
+ ok(result == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", result);
+ status = RtlDeregisterWait(wait1);
+ ok(!status || broken(status == STATUS_PENDING) /* >= Win 8 */,
+ "RtlDeregisterWait failed with status %x\n", status);
+
+ /* test RtlDeregisterWaitEx before wait expired */
+ info.userdata = 0;
+ status = RtlRegisterWait(&wait1, semaphores[1], rtl_wait_cb, &info, INFINITE, WT_EXECUTEDEFAULT);
+ ok(!status, "RtlRegisterWait failed with status %x\n", status);
+ status = RtlDeregisterWaitEx(wait1, NULL);
+ ok(!status, "RtlDeregisterWaitEx failed with status %x\n", status);
+ ok(info.userdata == 0, "expected info.userdata = 0, got %u\n", info.userdata);
+
+ info.userdata = 0;
+ status = RtlRegisterWait(&wait1, semaphores[1], rtl_wait_cb, &info, INFINITE, WT_EXECUTEDEFAULT);
+ ok(!status, "RtlRegisterWait failed with status %x\n", status);
+ status = RtlDeregisterWaitEx(wait1, INVALID_HANDLE_VALUE);
+ ok(!status, "RtlDeregisterWaitEx failed with status %x\n", status);
+ ok(info.userdata == 0, "expected info.userdata = 0, got %u\n", info.userdata);
+
+ info.userdata = 0;
+ status = RtlRegisterWait(&wait1, semaphores[1], rtl_wait_cb, &info, INFINITE, WT_EXECUTEDEFAULT);
+ ok(!status, "RtlRegisterWait failed with status %x\n", status);
+ status = RtlDeregisterWaitEx(wait1, event);
+ ok(!status, "RtlDeregisterWaitEx failed with status %x\n", status);
+ ok(info.userdata == 0, "expected info.userdata = 0, got %u\n", info.userdata);
+ result = WaitForSingleObject(event, 200);
+ todo_wine
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+
+ /* test RtlDeregisterWaitEx after wait expired */
+ info.userdata = 0;
+ status = RtlRegisterWait(&wait1, semaphores[1], rtl_wait_cb, &info, 0, WT_EXECUTEONLYONCE);
+ ok(!status, "RtlRegisterWait failed with status %x\n", status);
+ result = WaitForSingleObject(semaphores[0], 100);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(info.userdata == 0x10000, "expected info.userdata = 0x10000, got %u\n", info.userdata);
+ Sleep(50);
+ status = RtlDeregisterWaitEx(wait1, NULL);
+ ok(!status, "RtlDeregisterWaitEx failed with status %x\n", status);
+ ok(info.userdata == 0x10000, "expected info.userdata = 0x10000, got %u\n", info.userdata);
+
+ info.userdata = 0;
+ status = RtlRegisterWait(&wait1, semaphores[1], rtl_wait_cb, &info, 0, WT_EXECUTEONLYONCE);
+ ok(!status, "RtlRegisterWait failed with status %x\n", status);
+ result = WaitForSingleObject(semaphores[0], 100);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(info.userdata == 0x10000, "expected info.userdata = 0x10000, got %u\n", info.userdata);
+ Sleep(50);
+ status = RtlDeregisterWaitEx(wait1, INVALID_HANDLE_VALUE);
+ ok(!status, "RtlDeregisterWaitEx failed with status %x\n", status);
+ ok(info.userdata == 0x10000, "expected info.userdata = 0x10000, got %u\n", info.userdata);
+
+ info.userdata = 0;
+ status = RtlRegisterWait(&wait1, semaphores[1], rtl_wait_cb, &info, 0, WT_EXECUTEONLYONCE);
+ ok(!status, "RtlRegisterWait failed with status %x\n", status);
+ result = WaitForSingleObject(semaphores[0], 100);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(info.userdata == 0x10000, "expected info.userdata = 0x10000, got %u\n", info.userdata);
+ Sleep(50);
+ status = RtlDeregisterWaitEx(wait1, event);
+ ok(!status, "RtlDeregisterWaitEx failed with status %x\n", status);
+ ok(info.userdata == 0x10000, "expected info.userdata = 0x10000, got %u\n", info.userdata);
+ result = WaitForSingleObject(event, 200);
+ todo_wine
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+
+ /* test RtlDeregisterWaitEx while callback is running */
+ info.semaphore2 = semaphores[1];
+ info.wait_result = WAIT_OBJECT_0;
+
+ info.userdata = 0;
+ status = RtlRegisterWait(&wait1, semaphores[1], rtl_wait_cb, &info, INFINITE, WT_EXECUTEONLYONCE);
+ ok(!status, "RtlRegisterWait failed with status %x\n", status);
+ ReleaseSemaphore(semaphores[1], 1, NULL);
+ result = WaitForSingleObject(semaphores[0], 1000);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(info.userdata == 1, "expected info.userdata = 1, got %u\n", info.userdata);
+ status = RtlDeregisterWait(wait1);
+ ok(status == STATUS_PENDING, "expected STATUS_PENDING, got %x\n", status);
+ ReleaseSemaphore(semaphores[1], 1, NULL);
+ result = WaitForSingleObject(semaphores[0], 1000);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+
+ info.userdata = 0;
+ status = RtlRegisterWait(&wait1, semaphores[1], rtl_wait_cb, &info, INFINITE, WT_EXECUTEONLYONCE);
+ ok(!status, "RtlRegisterWait failed with status %x\n", status);
+ ReleaseSemaphore(semaphores[1], 1, NULL);
+ result = WaitForSingleObject(semaphores[0], 1000);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(info.userdata == 1, "expected info.userdata = 1, got %u\n", info.userdata);
+ status = RtlDeregisterWaitEx(wait1, NULL);
+ ok(status == STATUS_PENDING, "expected STATUS_PENDING, got %x\n", status);
+ ReleaseSemaphore(semaphores[1], 1, NULL);
+ result = WaitForSingleObject(semaphores[0], 1000);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+
+ info.wait_result = WAIT_TIMEOUT;
+ info.userdata = 0;
+ status = RtlRegisterWait(&wait1, semaphores[1], rtl_wait_cb, &info, INFINITE, WT_EXECUTEONLYONCE);
+ ok(!status, "RtlRegisterWait failed with status %x\n", status);
+ ReleaseSemaphore(semaphores[1], 1, NULL);
+ result = WaitForSingleObject(semaphores[0], 1000);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(info.userdata == 1, "expected info.userdata = 1, got %u\n", info.userdata);
+ status = RtlDeregisterWaitEx(wait1, INVALID_HANDLE_VALUE);
+ ok(!status, "RtlDeregisterWaitEx failed with status %x\n", status);
+ result = WaitForSingleObject(semaphores[0], 0);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+
+ info.wait_result = WAIT_OBJECT_0;
+ info.userdata = 0;
+ status = RtlRegisterWait(&wait1, semaphores[1], rtl_wait_cb, &info, INFINITE, WT_EXECUTEONLYONCE);
+ ok(!status, "RtlRegisterWait failed with status %x\n", status);
+ ReleaseSemaphore(semaphores[1], 1, NULL);
+ result = WaitForSingleObject(semaphores[0], 1000);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ ok(info.userdata == 1, "expected info.userdata = 1, got %u\n", info.userdata);
+ status = RtlDeregisterWaitEx(wait1, event);
+ ok(status == STATUS_PENDING, "expected STATUS_PENDING, got %x\n", status);
+ ReleaseSemaphore(semaphores[1], 1, NULL);
+ result = WaitForSingleObject(event, 1000);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ result = WaitForSingleObject(semaphores[0], 0);
+ ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+
+ CloseHandle(semaphores[0]);
+ CloseHandle(semaphores[1]);
+ CloseHandle(event);
+}
+
static void CALLBACK simple_cb(TP_CALLBACK_INSTANCE *instance, void *userdata)
{
HANDLE semaphore = userdata;
@@ -1340,6 +1592,7 @@ static void test_tp_multi_wait(void)
START_TEST(threadpool)
{
test_RtlQueueWorkItem();
+ test_RtlRegisterWait();
if (!init_threadpool())
return;
--
2.6.0
More information about the wine-patches
mailing list