mirror of
https://github.com/reactos/reactos.git
synced 2024-11-02 04:37:32 +00:00
186 lines
4.1 KiB
C
186 lines
4.1 KiB
C
/*
|
|
* PROJECT: ReactOS api tests
|
|
* LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later)
|
|
* PURPOSE: Tests for QueueUserAPC, SleepEx, WaitForSingleObjectEx etc.
|
|
* COPYRIGHT: Copyright 2020 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
|
|
*/
|
|
#include "precomp.h"
|
|
|
|
#define MAX_RECORD 30
|
|
|
|
static LONG s_record_count = 0;
|
|
static DWORD s_record[MAX_RECORD + 1] = { 0 };
|
|
static BOOL s_terminate_all = FALSE;
|
|
|
|
static const DWORD s_expected[] =
|
|
{
|
|
0, 1, 7, 8, 4,
|
|
2, 1, 9, 10, 5,
|
|
2, 1, 11, 12, 13,
|
|
6, 2, 3, 14, 15,
|
|
16
|
|
};
|
|
static const SIZE_T s_expected_count = _countof(s_expected);
|
|
|
|
static void AddValueToRecord(DWORD dwValue)
|
|
{
|
|
LONG next = InterlockedIncrement(&s_record_count) - 1;
|
|
if (next < MAX_RECORD)
|
|
s_record[next] = dwValue;
|
|
}
|
|
|
|
static VOID CheckRecord(void)
|
|
{
|
|
SIZE_T i, count = min(s_record_count, s_expected_count);
|
|
|
|
for (i = 0; i < count; ++i)
|
|
{
|
|
ok(s_record[i] == s_expected[i], "s_record[%u]: got %lu vs expected %lu\n",
|
|
(INT)i, s_record[i], s_expected[i]);
|
|
}
|
|
|
|
count = abs((int)s_record_count - (int)s_expected_count);
|
|
for (i = 0; i < count; ++i)
|
|
{
|
|
ok(s_record_count == s_expected_count,
|
|
"s_record_count: got %u vs expected %u\n",
|
|
(int)s_record_count, (int)s_expected_count);
|
|
}
|
|
}
|
|
|
|
static DWORD WINAPI ThreadFunc1(LPVOID arg)
|
|
{
|
|
AddValueToRecord(0);
|
|
while (!s_terminate_all)
|
|
{
|
|
AddValueToRecord(1);
|
|
ok_long(SleepEx(INFINITE, TRUE), WAIT_IO_COMPLETION);
|
|
AddValueToRecord(2);
|
|
}
|
|
AddValueToRecord(3);
|
|
return 0;
|
|
}
|
|
|
|
static DWORD WINAPI ThreadFunc2(LPVOID arg)
|
|
{
|
|
AddValueToRecord(0);
|
|
while (!s_terminate_all)
|
|
{
|
|
AddValueToRecord(1);
|
|
ok_long(WaitForSingleObjectEx(GetCurrentThread(), INFINITE, TRUE), WAIT_IO_COMPLETION);
|
|
AddValueToRecord(2);
|
|
}
|
|
AddValueToRecord(3);
|
|
return 0;
|
|
}
|
|
|
|
static VOID NTAPI DoUserAPC1(ULONG_PTR Parameter)
|
|
{
|
|
ok_int((int)Parameter, 1);
|
|
AddValueToRecord(4);
|
|
}
|
|
|
|
static VOID NTAPI DoUserAPC2(ULONG_PTR Parameter)
|
|
{
|
|
ok_int((int)Parameter, 2);
|
|
AddValueToRecord(5);
|
|
}
|
|
|
|
static VOID NTAPI DoUserAPC3(ULONG_PTR Parameter)
|
|
{
|
|
ok_int((int)Parameter, 3);
|
|
AddValueToRecord(6);
|
|
s_terminate_all = TRUE;
|
|
}
|
|
|
|
static void JustDoIt(LPTHREAD_START_ROUTINE fn)
|
|
{
|
|
HANDLE hThread;
|
|
DWORD dwThreadId;
|
|
|
|
s_terminate_all = FALSE;
|
|
s_record_count = 0;
|
|
ZeroMemory(s_record, sizeof(s_record));
|
|
|
|
hThread = CreateThread(NULL, 0, fn, NULL, 0, &dwThreadId);
|
|
ok(hThread != NULL, "hThread was NULL\n");
|
|
|
|
Sleep(100);
|
|
|
|
AddValueToRecord(7);
|
|
ok_long(QueueUserAPC(DoUserAPC1, hThread, 1), 1);
|
|
AddValueToRecord(8);
|
|
|
|
Sleep(100);
|
|
|
|
AddValueToRecord(9);
|
|
ok_long(QueueUserAPC(DoUserAPC2, hThread, 2), 1);
|
|
AddValueToRecord(10);
|
|
|
|
Sleep(100);
|
|
|
|
AddValueToRecord(11);
|
|
ok_long(QueueUserAPC(DoUserAPC3, hThread, 3), 1);
|
|
AddValueToRecord(12);
|
|
|
|
AddValueToRecord(13);
|
|
ok_long(WaitForSingleObject(hThread, 5 * 1000), WAIT_OBJECT_0);
|
|
AddValueToRecord(14);
|
|
|
|
AddValueToRecord(15);
|
|
ok_int(CloseHandle(hThread), TRUE);
|
|
hThread = NULL;
|
|
AddValueToRecord(16);
|
|
|
|
CheckRecord();
|
|
}
|
|
|
|
static void TestForSleepEx(void)
|
|
{
|
|
JustDoIt(ThreadFunc1);
|
|
}
|
|
|
|
static void TestForWaitForSingleObjectEx(void)
|
|
{
|
|
JustDoIt(ThreadFunc2);
|
|
}
|
|
|
|
static DWORD WINAPI ThreadFunc3(LPVOID arg)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static void TestMultipleUserAPCs(void)
|
|
{
|
|
HANDLE hThread;
|
|
DWORD dwThreadId;
|
|
|
|
s_record_count = 0;
|
|
|
|
hThread = CreateThread(NULL, 0, ThreadFunc3, NULL, CREATE_SUSPENDED, &dwThreadId);
|
|
ok(hThread != NULL, "hThread was NULL\n");
|
|
|
|
ok_long(QueueUserAPC(DoUserAPC1, hThread, 1), 1);
|
|
ok_long(QueueUserAPC(DoUserAPC2, hThread, 2), 1);
|
|
ok_long(QueueUserAPC(DoUserAPC3, hThread, 3), 1);
|
|
|
|
ok_long(s_record_count, 0);
|
|
|
|
ResumeThread(hThread);
|
|
|
|
ok_long(WaitForSingleObject(hThread, 5 * 1000), WAIT_OBJECT_0);
|
|
ok_int(CloseHandle(hThread), TRUE);
|
|
|
|
ok_long(s_record_count, 3);
|
|
ok_long(s_record[0], 4);
|
|
ok_long(s_record[1], 5);
|
|
ok_long(s_record[2], 6);
|
|
}
|
|
|
|
START_TEST(QueueUserAPC)
|
|
{
|
|
TestForSleepEx();
|
|
TestForWaitForSingleObjectEx();
|
|
TestMultipleUserAPCs();
|
|
}
|