diff --git a/modules/rostests/apitests/win32nt/ntuser/NtUserSetTimer.c b/modules/rostests/apitests/win32nt/ntuser/NtUserSetTimer.c index aad40f49698..ccdc6da4602 100644 --- a/modules/rostests/apitests/win32nt/ntuser/NtUserSetTimer.c +++ b/modules/rostests/apitests/win32nt/ntuser/NtUserSetTimer.c @@ -1,18 +1,256 @@ /* - * PROJECT: ReactOS api tests - * LICENSE: GPL - See COPYING in the top level directory - * PURPOSE: Test for NtUserSetTimer - * PROGRAMMERS: + * PROJECT: ReactOS API tests + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: Tests for NtUserSetTimer + * COPYRIGHT: Copyright 2008 Timo Kreuzer + * Copyright 2024 Tomáš Veselý */ #include "../win32nt.h" +#define SLEEP_TIME 500 +#define TIME_TOLERANCE 0.5 + +#define TEST1_COUNT 20 +#define TEST1_INTERVAL 10 + +#define TEST2_COUNT 40000 +#define TEST2_INTERVAL 10 + +#define TESTW1_COUNT 20 +#define TESTW1_INTERVAL 10 + +#define TESTW2_COUNT 40000 +#define TESTW2_INTERVAL 10 + +typedef struct TIMER_MESSAGE_STATE1 +{ + UINT_PTR index; + UINT counter; +} TIMER_MESSAGE_STATE1; + +TIMER_MESSAGE_STATE1 timerId1[TEST1_COUNT]; + +typedef struct TIMER_MESSAGE_STATEW1 +{ + UINT counter; +} TIMER_MESSAGE_STATEW1; + +TIMER_MESSAGE_STATEW1 timerIdW1[TESTW1_COUNT]; + +/* TIMERPROC for the test1,2,3() with messages without window */ +static void CALLBACK +TimerProc(HWND hWnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) +{ + UINT i; + for (i = 0; i < TEST1_COUNT; i++) + { + if (timerId1[i].index == idEvent) + timerId1[i].counter++; + } +} + +/* TIMERPROC for the testW1,2() with messages with window */ +static LRESULT CALLBACK +WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_TIMER: + timerIdW1[wParam].counter++; + return 0; + } + + return DefWindowProcW(hwnd, uMsg, wParam, lParam); +} + +// TEST WITH MESSAGES WITHOUT WINDOW - test count of sent messages +static BOOL test1(void) +{ + UINT i, countErrors = 0; + ULONGLONG startTime; + MSG msg = { NULL }; + + int minMessages = ((float)SLEEP_TIME / (float)TEST1_INTERVAL) * (1 - TIME_TOLERANCE); + int maxMessages = ((float)SLEEP_TIME / (float)TEST1_INTERVAL) * (1 + TIME_TOLERANCE); + + ZeroMemory(timerId1, sizeof(timerId1)); + + for (i = 0; i < TEST1_COUNT; i++) + { + timerId1[i].index = SetTimer(NULL, 0, TEST1_INTERVAL, TimerProc); + if (timerId1[i].index == 0) + countErrors++; + } + + startTime = GetTickCount(); + + while (GetMessageW(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessageW(&msg); + + if (GetTickCount() - startTime >= SLEEP_TIME) + PostQuitMessage(0); + } + + for (i = 0; i < TEST1_COUNT; i++) + { + if ((timerId1[i].counter < minMessages) || (timerId1[i].counter > maxMessages)) + countErrors++; + } + + for (i = 0; i < TEST1_COUNT; i++) + { + if (KillTimer(NULL, timerId1[i].index) == 0) + countErrors++; + } + + return (countErrors == 0); +} + +// TEST WITH MESSAGES WITHOUT WINDOW - create many timers +static BOOL test2(void) +{ + UINT i, countErrors = 0; + UINT_PTR locIndex; + + for (i = 0; i < TEST2_COUNT; i++) + { + locIndex = SetTimer(NULL, 0, TEST2_INTERVAL, TimerProc); + + if (locIndex == 0) + countErrors++; + if (KillTimer(NULL, locIndex) == 0) + countErrors++; + } + + return (countErrors == 0); +} + +// TEST WITH MESSAGES WITHOUT WINDOW - test different ids +static BOOL test3(void) +{ + UINT countErrors = 0; + UINT_PTR locIndex1; + UINT_PTR locIndex2; + + locIndex1 = SetTimer(NULL, 0, TEST1_INTERVAL, TimerProc); + if (locIndex1 == 0) + countErrors++; + if (KillTimer(NULL, locIndex1) == 0) + countErrors++; + locIndex2 = SetTimer(NULL, 0, TEST1_INTERVAL, TimerProc); + if (locIndex2 == 0) + countErrors++; + if (KillTimer(NULL, locIndex2) == 0) + countErrors++; + if (locIndex1 == locIndex2) + countErrors++; + + return (countErrors == 0); +} + +// TEST WITH MESSAGES WITH WINDOW - test count of sent messages +static BOOL testW1(HWND hwnd) +{ + UINT i, countErrors = 0; + UINT_PTR locIndex; + ULONGLONG startTime; + MSG msg = { NULL }; + + if (hwnd == NULL) + return FALSE; + + int minMessages = ((float)SLEEP_TIME / (float)TESTW1_INTERVAL) * (1 - TIME_TOLERANCE); + int maxMessages = ((float)SLEEP_TIME / (float)TESTW1_INTERVAL) * (1 + TIME_TOLERANCE); + + ZeroMemory(timerIdW1, sizeof(timerIdW1)); + + for (i = 0; i < TESTW1_COUNT; i++) + { + locIndex = SetTimer(hwnd, i, TESTW1_INTERVAL, NULL); + if (locIndex == 0) + countErrors++; + } + + startTime = GetTickCount(); + + while (GetMessageW(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessageW(&msg); + + if (GetTickCount() - startTime >= SLEEP_TIME) + PostQuitMessage(0); + } + + for (i = 0; i < TESTW1_COUNT; i++) + { + if ((timerIdW1[i].counter < minMessages) || (timerIdW1[i].counter > maxMessages)) + countErrors++; + } + + for (i = 0; i < TESTW1_COUNT; i++) + { + if (KillTimer(hwnd, i) == 0) + countErrors++; + } + + return (countErrors == 0); +} + +// TEST WITH MESSAGES WITH WINDOW - create many timers +static BOOL testW2(HWND hwnd) +{ + UINT i, countErrors = 0; + UINT_PTR result; + + if (hwnd == NULL) + return FALSE; + + for (i = 0; i < TESTW2_COUNT; i++) + { + result = SetTimer(hwnd, 1, TESTW2_INTERVAL, NULL); + if (result == 0) + countErrors++; + if (KillTimer(hwnd, 1) == 0) + countErrors++; + } + + return (countErrors == 0); +} + START_TEST(NtUserSetTimer) { + WNDCLASSW wc = { 0 }; + HWND hwnd; + // TEST WITH MESSAGES WITHOUT WINDOW - test count of sent messages + TEST(test1()); - // check valid argument - // check for replacement / new timers - // check when expiries are handled (msgs and calls) + // TEST WITH MESSAGES WITHOUT WINDOW - create many timers + TEST(test2()); + // TEST WITH MESSAGES WITHOUT WINDOW - test different ids + TEST(test3()); + + wc.lpfnWndProc = WindowProc; + wc.hInstance = GetModuleHandleW(NULL); + wc.lpszClassName = L"TimerWindowClass"; + RegisterClassW(&wc); + + hwnd = CreateWindowExW(0, L"TimerWindowClass", L"Timer Window", 0, + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + HWND_MESSAGE, NULL, GetModuleHandleW(NULL), NULL); + + // TEST WITH MESSAGES WITH WINDOW - test count of sent messages + TEST(testW1(hwnd)); + + // TEST WITH MESSAGES WITH WINDOW - create many timers + TEST(testW2(hwnd)); + + if (hwnd != NULL) + DestroyWindow(hwnd); + UnregisterClassW(L"TimerWindowClass", NULL); }