user32/tests: Improve timer measurement method.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=55786
This commit is contained in:
parent
d81256e7b6
commit
0f0867063d
1 changed files with 71 additions and 35 deletions
|
@ -11548,20 +11548,67 @@ static VOID CALLBACK tfunc(HWND hwnd, UINT uMsg, UINT_PTR id, DWORD dwTime)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#define TIMER_ID 0x19
|
#define TIMER_ID 0x19
|
||||||
#define TIMER_COUNT_EXPECTED 100
|
#define TIMER_COUNT 500 /* 499 samples */
|
||||||
#define TIMER_COUNT_TOLERANCE 10
|
#define TIMER_DURATION_EXPECTED 10000 /* 10 ms */
|
||||||
|
#define TIMER_DURATION_ALT 15600 /* 15.6 ms */
|
||||||
|
#define TIMER_DURATION_TOLERANCE 1000 /* 1 ms */
|
||||||
|
|
||||||
static int count = 0;
|
static int count = 0;
|
||||||
|
static ULONGLONG timer_ticks[TIMER_COUNT];
|
||||||
|
static int timer_duration = 0;
|
||||||
|
|
||||||
|
static int compare_ulonglong(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
ULONGLONG la, lb;
|
||||||
|
la = *(ULONGLONG*)a;
|
||||||
|
lb = *(ULONGLONG*)b;
|
||||||
|
return (la > lb) - (la < lb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void timer_fired(void)
|
||||||
|
{
|
||||||
|
if (count < TIMER_COUNT)
|
||||||
|
{
|
||||||
|
LARGE_INTEGER performance_counter;
|
||||||
|
BOOL ret;
|
||||||
|
|
||||||
|
ret = QueryPerformanceCounter(&performance_counter);
|
||||||
|
ok(ret, "QueryPerformanceCounter failed\n");
|
||||||
|
|
||||||
|
timer_ticks[count] = performance_counter.QuadPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
count++;
|
||||||
|
|
||||||
|
if (count == TIMER_COUNT)
|
||||||
|
{
|
||||||
|
LARGE_INTEGER performance_frequency;
|
||||||
|
BOOL ret;
|
||||||
|
|
||||||
|
/* calculate durations */
|
||||||
|
for (int i=0; i < TIMER_COUNT-1; i++)
|
||||||
|
timer_ticks[i] = timer_ticks[i+1] - timer_ticks[i];
|
||||||
|
|
||||||
|
qsort(timer_ticks, TIMER_COUNT - 1, sizeof(timer_ticks[0]), compare_ulonglong);
|
||||||
|
|
||||||
|
ret = QueryPerformanceFrequency(&performance_frequency);
|
||||||
|
ok(ret, "QueryPerformanceFrequency failed\n");
|
||||||
|
|
||||||
|
/* median duration, converted to microseconds */
|
||||||
|
timer_duration = (int)(timer_ticks[(TIMER_COUNT - 1) / 2] * 1000000 / performance_frequency.QuadPart);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void CALLBACK callback_count(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
|
static void CALLBACK callback_count(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
|
||||||
{
|
{
|
||||||
count++;
|
timer_fired();
|
||||||
}
|
}
|
||||||
|
|
||||||
static DWORD exception;
|
static DWORD exception;
|
||||||
static void CALLBACK callback_exception(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
|
static void CALLBACK callback_exception(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
|
||||||
{
|
{
|
||||||
count++;
|
timer_fired();
|
||||||
RaiseException(exception, 0, 0, NULL);
|
RaiseException(exception, 0, 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11583,7 +11630,6 @@ static DWORD WINAPI timer_thread_proc(LPVOID x)
|
||||||
static void test_timers(void)
|
static void test_timers(void)
|
||||||
{
|
{
|
||||||
struct timer_info info;
|
struct timer_info info;
|
||||||
DWORD start;
|
|
||||||
DWORD id;
|
DWORD id;
|
||||||
MSG msg;
|
MSG msg;
|
||||||
|
|
||||||
|
@ -11609,44 +11655,37 @@ static void test_timers(void)
|
||||||
|
|
||||||
/* Check the minimum allowed timeout for a timer. MSDN indicates that it should be 10.0 ms,
|
/* Check the minimum allowed timeout for a timer. MSDN indicates that it should be 10.0 ms,
|
||||||
* which occurs sometimes, but most testing on the VMs indicates a minimum timeout closer to
|
* which occurs sometimes, but most testing on the VMs indicates a minimum timeout closer to
|
||||||
* 15.6 ms. Since there is some measurement error between test runs we are allowing for
|
* 15.6 ms.
|
||||||
* ±9 counts (~4 ms) around the expected value.
|
|
||||||
*/
|
*/
|
||||||
count = 0;
|
count = 0;
|
||||||
id = SetTimer(info.hWnd, TIMER_ID, 0, callback_count);
|
id = SetTimer(info.hWnd, TIMER_ID, 0, callback_count);
|
||||||
ok(id != 0, "did not get id from SetTimer.\n");
|
ok(id != 0, "did not get id from SetTimer.\n");
|
||||||
ok(id==TIMER_ID, "SetTimer timer ID different\n");
|
ok(id==TIMER_ID, "SetTimer timer ID different\n");
|
||||||
start = GetTickCount();
|
while (count < TIMER_COUNT && GetMessageA(&msg, info.hWnd, 0, 0))
|
||||||
while (GetTickCount()-start < 1001 && GetMessageA(&msg, info.hWnd, 0, 0))
|
|
||||||
DispatchMessageA(&msg);
|
DispatchMessageA(&msg);
|
||||||
ok(abs(count-TIMER_COUNT_EXPECTED) < TIMER_COUNT_TOLERANCE /* xp */
|
ok(abs(timer_duration-TIMER_DURATION_EXPECTED) < TIMER_DURATION_TOLERANCE /* xp, win7 */
|
||||||
|| broken(abs(count-64) <= TIMER_COUNT_TOLERANCE) /* most common */
|
|| broken(abs(timer_duration - TIMER_DURATION_ALT) < TIMER_DURATION_TOLERANCE) /* most common */,
|
||||||
|| broken(abs(count-43) <= TIMER_COUNT_TOLERANCE) /* w2k3, win8 */,
|
"did not get expected median timeout (%d != ~%d).\n",
|
||||||
"did not get expected count for minimum timeout (%d != ~%d).\n",
|
timer_duration, TIMER_DURATION_EXPECTED);
|
||||||
count, TIMER_COUNT_EXPECTED);
|
|
||||||
ok(KillTimer(info.hWnd, id), "KillTimer failed\n");
|
ok(KillTimer(info.hWnd, id), "KillTimer failed\n");
|
||||||
/* Perform the same check on SetSystemTimer (only available on w2k3 and older) */
|
/* Perform the same check on SetSystemTimer (only available on w2k3 and older) */
|
||||||
if (pSetSystemTimer)
|
if (pSetSystemTimer)
|
||||||
{
|
{
|
||||||
int syscount = 0;
|
|
||||||
|
|
||||||
count = 0;
|
count = 0;
|
||||||
id = pSetSystemTimer(info.hWnd, TIMER_ID, 0, callback_count);
|
id = pSetSystemTimer(info.hWnd, TIMER_ID, 0, callback_count);
|
||||||
ok(id != 0, "did not get id from SetSystemTimer.\n");
|
ok(id != 0, "did not get id from SetSystemTimer.\n");
|
||||||
ok(id==TIMER_ID, "SetTimer timer ID different\n");
|
ok(id==TIMER_ID, "SetTimer timer ID different\n");
|
||||||
start = GetTickCount();
|
while (count < TIMER_COUNT && GetMessageA(&msg, info.hWnd, 0, 0))
|
||||||
while (GetTickCount()-start < 1001 && GetMessageA(&msg, info.hWnd, 0, 0))
|
|
||||||
{
|
{
|
||||||
if (msg.message == WM_SYSTIMER)
|
if (msg.message == WM_SYSTIMER)
|
||||||
syscount++;
|
timer_fired();
|
||||||
|
ok(msg.message != WM_TIMER, "unexpected WM_TIMER\n");
|
||||||
DispatchMessageA(&msg);
|
DispatchMessageA(&msg);
|
||||||
}
|
}
|
||||||
ok(abs(syscount-TIMER_COUNT_EXPECTED) < TIMER_COUNT_TOLERANCE
|
ok(abs(timer_duration-TIMER_DURATION_EXPECTED) < TIMER_DURATION_TOLERANCE
|
||||||
|| broken(abs(syscount-64) < TIMER_COUNT_TOLERANCE) /* most common */
|
|| broken(abs(timer_duration - TIMER_DURATION_ALT) < TIMER_DURATION_TOLERANCE) /* most common */,
|
||||||
|| broken(syscount > 4000 && syscount < 12000) /* win2k3sp0 */,
|
"did not get expected median timeout (%d != ~%d).\n",
|
||||||
"did not get expected count for minimum timeout (%d != ~%d).\n",
|
timer_duration, TIMER_DURATION_EXPECTED);
|
||||||
syscount, TIMER_COUNT_EXPECTED);
|
|
||||||
ok(count == 0, "did not get expected count for callback timeout (%d != 0).\n", count);
|
|
||||||
ok(pKillSystemTimer(info.hWnd, id), "KillSystemTimer failed\n");
|
ok(pKillSystemTimer(info.hWnd, id), "KillSystemTimer failed\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11679,20 +11718,17 @@ static void test_timers_no_wnd(void)
|
||||||
|
|
||||||
/* Check the minimum allowed timeout for a timer. MSDN indicates that it should be 10.0 ms,
|
/* Check the minimum allowed timeout for a timer. MSDN indicates that it should be 10.0 ms,
|
||||||
* which occurs sometimes, but most testing on the VMs indicates a minimum timeout closer to
|
* which occurs sometimes, but most testing on the VMs indicates a minimum timeout closer to
|
||||||
* 15.6 ms. Since there is some measurement error between test runs we are allowing for
|
* 15.6 ms.
|
||||||
* ±9 counts (~4 ms) around the expected value.
|
|
||||||
*/
|
*/
|
||||||
count = 0;
|
count = 0;
|
||||||
id = SetTimer(NULL, 0, 0, callback_count);
|
id = SetTimer(NULL, 0, 0, callback_count);
|
||||||
ok(id != 0, "did not get id from SetTimer.\n");
|
ok(id != 0, "did not get id from SetTimer.\n");
|
||||||
start = GetTickCount();
|
while (count < TIMER_COUNT && GetMessageA(&msg, NULL, 0, 0))
|
||||||
while (GetTickCount()-start < 1001 && GetMessageA(&msg, NULL, 0, 0))
|
|
||||||
DispatchMessageA(&msg);
|
DispatchMessageA(&msg);
|
||||||
ok(abs(count-TIMER_COUNT_EXPECTED) < TIMER_COUNT_TOLERANCE /* xp */
|
ok(abs(timer_duration-TIMER_DURATION_EXPECTED) < TIMER_DURATION_TOLERANCE /* xp */
|
||||||
|| broken(abs(count-64) <= TIMER_COUNT_TOLERANCE) /* most common */
|
|| broken(abs(timer_duration - TIMER_DURATION_ALT) < TIMER_DURATION_TOLERANCE) /* most common */,
|
||||||
|| broken(abs(count-43) <= TIMER_COUNT_TOLERANCE) /* w1064v1809 */,
|
"did not get expected median timeout (%d != ~%d).\n",
|
||||||
"did not get expected count for minimum timeout (%d != ~%d).\n",
|
timer_duration, TIMER_DURATION_EXPECTED);
|
||||||
count, TIMER_COUNT_EXPECTED);
|
|
||||||
KillTimer(NULL, id);
|
KillTimer(NULL, id);
|
||||||
/* Note: SetSystemTimer doesn't support a NULL window, see test_timers */
|
/* Note: SetSystemTimer doesn't support a NULL window, see test_timers */
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue