1 /* 2 * PROJECT: ReactOS api tests 3 * LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later) 4 * PURPOSE: Tests for QueueUserAPC, SleepEx, WaitForSingleObjectEx etc. 5 * COPYRIGHT: Copyright 2020 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com) 6 */ 7 #include "precomp.h" 8 9 #define MAX_RECORD 30 10 11 static DWORD s_record_count = 0; 12 static DWORD s_record[MAX_RECORD + 1] = { 0 }; 13 static BOOL s_terminate_all = FALSE; 14 15 static const DWORD s_expected[] = 16 { 17 0, 1, 7, 8, 4, 18 2, 1, 9, 10, 5, 19 2, 1, 11, 12, 13, 20 6, 2, 3, 14, 15, 21 16 22 }; 23 static const SIZE_T s_expected_count = _countof(s_expected); 24 25 static void AddValueToRecord(DWORD dwValue) 26 { 27 s_record[s_record_count] = dwValue; 28 if (s_record_count < MAX_RECORD) 29 s_record_count++; 30 } 31 32 static VOID CheckRecord(void) 33 { 34 SIZE_T i, count = min(s_record_count, s_expected_count); 35 36 for (i = 0; i < count; ++i) 37 { 38 ok(s_record[i] == s_expected[i], "s_record[%u]: got %lu vs expected %lu\n", 39 (INT)i, s_record[i], s_expected[i]); 40 } 41 42 count = abs((int)s_record_count - (int)s_expected_count); 43 for (i = 0; i < count; ++i) 44 { 45 ok(s_record_count == s_expected_count, 46 "s_record_count: got %u vs expected %u\n", 47 (int)s_record_count, (int)s_expected_count); 48 } 49 } 50 51 static DWORD WINAPI ThreadFunc1(LPVOID arg) 52 { 53 AddValueToRecord(0); 54 while (!s_terminate_all) 55 { 56 AddValueToRecord(1); 57 ok_long(SleepEx(INFINITE, TRUE), WAIT_IO_COMPLETION); 58 AddValueToRecord(2); 59 } 60 AddValueToRecord(3); 61 return 0; 62 } 63 64 static DWORD WINAPI ThreadFunc2(LPVOID arg) 65 { 66 AddValueToRecord(0); 67 while (!s_terminate_all) 68 { 69 AddValueToRecord(1); 70 ok_long(WaitForSingleObjectEx(GetCurrentThread(), INFINITE, TRUE), WAIT_IO_COMPLETION); 71 AddValueToRecord(2); 72 } 73 AddValueToRecord(3); 74 return 0; 75 } 76 77 static VOID NTAPI DoUserAPC1(ULONG_PTR Parameter) 78 { 79 ok_int((int)Parameter, 1); 80 AddValueToRecord(4); 81 } 82 83 static VOID NTAPI DoUserAPC2(ULONG_PTR Parameter) 84 { 85 ok_int((int)Parameter, 2); 86 AddValueToRecord(5); 87 } 88 89 static VOID NTAPI DoUserAPC3(ULONG_PTR Parameter) 90 { 91 ok_int((int)Parameter, 3); 92 AddValueToRecord(6); 93 s_terminate_all = TRUE; 94 } 95 96 static void JustDoIt(LPTHREAD_START_ROUTINE fn) 97 { 98 HANDLE hThread; 99 DWORD dwThreadId; 100 101 s_terminate_all = FALSE; 102 s_record_count = 0; 103 ZeroMemory(s_record, sizeof(s_record)); 104 105 hThread = CreateThread(NULL, 0, fn, NULL, 0, &dwThreadId); 106 ok(hThread != NULL, "hThread was NULL\n"); 107 108 Sleep(100); 109 110 AddValueToRecord(7); 111 ok_long(QueueUserAPC(DoUserAPC1, hThread, 1), 1); 112 AddValueToRecord(8); 113 114 Sleep(100); 115 116 AddValueToRecord(9); 117 ok_long(QueueUserAPC(DoUserAPC2, hThread, 2), 1); 118 AddValueToRecord(10); 119 120 Sleep(100); 121 122 AddValueToRecord(11); 123 ok_long(QueueUserAPC(DoUserAPC3, hThread, 3), 1); 124 AddValueToRecord(12); 125 126 AddValueToRecord(13); 127 ok_long(WaitForSingleObject(hThread, 5 * 1000), WAIT_OBJECT_0); 128 AddValueToRecord(14); 129 130 AddValueToRecord(15); 131 ok_int(CloseHandle(hThread), TRUE); 132 hThread = NULL; 133 AddValueToRecord(16); 134 135 CheckRecord(); 136 } 137 138 static void TestForSleepEx(void) 139 { 140 JustDoIt(ThreadFunc1); 141 } 142 143 static void TestForWaitForSingleObjectEx(void) 144 { 145 JustDoIt(ThreadFunc2); 146 } 147 148 START_TEST(QueueUserAPC) 149 { 150 TestForSleepEx(); 151 TestForWaitForSingleObjectEx(); 152 } 153