timer.c 6.38 KB
Newer Older
Mike McCormack's avatar
Mike McCormack committed
1
/*
2
 * Unit test suite for timer functions
Mike McCormack's avatar
Mike McCormack committed
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
 *
 * Copyright 2004 Mike McCormack
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
Mike McCormack's avatar
Mike McCormack committed
19 20 21 22
 */

#include "wine/test.h"
#include "winbase.h"
23 24
#include "winternl.h"
#include "winuser.h"
Mike McCormack's avatar
Mike McCormack committed
25 26


27
static void test_timer(void)
Mike McCormack's avatar
Mike McCormack committed
28 29 30 31 32 33
{
    HANDLE handle;
    BOOL r;
    LARGE_INTEGER due;

    /* try once with a positive number */
34
    handle = CreateWaitableTimerA( NULL, 0, NULL );
Mike McCormack's avatar
Mike McCormack committed
35 36 37
    ok( handle != NULL, "failed to create waitable timer with no name\n" );

    due.QuadPart = 10000;
38
    r = SetWaitableTimer( handle, &due, 0x1f4, NULL, NULL, FALSE );
Mike McCormack's avatar
Mike McCormack committed
39 40 41 42 43
    ok( r, "failed to set timer\n");

    CloseHandle( handle );

    /* try once with a negative number */
44
    handle = CreateWaitableTimerA( NULL, 0, NULL );
Mike McCormack's avatar
Mike McCormack committed
45 46 47
    ok( handle != NULL, "failed to create waitable timer with no name\n" );

    due.QuadPart = -10000;
48
    r = SetWaitableTimer( handle, &due, 0x1f4, NULL, NULL, FALSE );
Mike McCormack's avatar
Mike McCormack committed
49 50 51 52 53
    ok( r, "failed to set timer\n");

    CloseHandle( handle );
}

54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
#define TICKSPERSEC       10000000

static BOOL adjust_system_time(int sec)
{
    ULARGE_INTEGER uli;
    SYSTEMTIME st;
    FILETIME ft;

    GetSystemTimeAsFileTime(&ft);
    uli.u.LowPart = ft.dwLowDateTime;
    uli.u.HighPart = ft.dwHighDateTime;
    uli.QuadPart += (LONGLONG)sec * TICKSPERSEC;
    ft.dwLowDateTime = uli.u.LowPart;
    ft.dwHighDateTime = uli.u.HighPart;
    if (!FileTimeToSystemTime(&ft, &st))
        return FALSE;
    return SetSystemTime(&st);
}

static DWORD WINAPI thread_WaitForSingleObject(void *arg)
{
    HANDLE event;
    DWORD t, r;

    event = CreateEventW(NULL, FALSE, FALSE, NULL);
    ok(event != NULL, "CreateEvent failed\n");
    t = GetTickCount();
    r = WaitForSingleObject(event, 3000);
82
    ok(r == WAIT_TIMEOUT, "WiatForSingleObject returned %lx\n", r);
83 84
    CloseHandle(event);
    t = GetTickCount() - t;
85
    ok(t > 2000, "t = %ld\n", t);
86 87 88 89 90 91 92 93 94
    return 0;
}

static DWORD WINAPI thread_Sleep(void *arg)
{
    DWORD t = GetTickCount();

    Sleep(3000);
    t = GetTickCount() - t;
95
    ok(t > 2000, "t = %ld\n", t);
96 97 98 99 100 101 102 103 104
    return 0;
}

static DWORD WINAPI thread_SleepEx(void *arg)
{
    DWORD t = GetTickCount();

    SleepEx(3000, TRUE);
    t = GetTickCount() - t;
105
    ok(t > 2000, "t = %ld\n", t);
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
    return 0;
}

static DWORD WINAPI thread_WaitableTimer_rel(void *arg)
{
    LARGE_INTEGER li;
    HANDLE timer;
    DWORD t, r;

    li.QuadPart = -3 * TICKSPERSEC;

    timer = CreateWaitableTimerA(NULL, TRUE, NULL);
    ok(timer != NULL, "CreateWaitableTimer failed\n");

    t = GetTickCount();
    r = SetWaitableTimer(timer, &li, 0, NULL, NULL, FALSE);
    ok(r, "SetWaitableTimer failed\n");

    r = WaitForSingleObject(timer, INFINITE);
125
    ok(r == WAIT_OBJECT_0, "WaitForSingleObject returned %ld\n", r);
126 127
    CloseHandle(timer);
    t = GetTickCount() - t;
128
    ok(t > 2000, "t = %ld\n", t);
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
    return 0;
}

static DWORD WINAPI thread_WaitableTimer_abs(void *arg)
{
    LARGE_INTEGER li;
    HANDLE timer;
    FILETIME ft;
    DWORD t, r;

    GetSystemTimeAsFileTime(&ft);
    li.u.LowPart = ft.dwLowDateTime;
    li.u.HighPart = ft.dwHighDateTime;
    li.QuadPart += 3 * TICKSPERSEC;

    timer = CreateWaitableTimerA(NULL, TRUE, NULL);
    ok(timer != NULL, "CreateWaitableTimer failed\n");

    t = GetTickCount();
    r = SetWaitableTimer(timer, &li, 0, NULL, NULL, FALSE);
    ok(r, "SetWaitableTimer failed\n");

    r = WaitForSingleObject(timer, INFINITE);
152
    ok(r == WAIT_OBJECT_0, "WaitForSingleObject returned %ld\n", r);
153 154
    CloseHandle(timer);
    t = GetTickCount() - t;
155
    ok(t < 2000, "t = %ld\n", t);
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
    return 0;
}

static DWORD WINAPI thread_WaitableTimer_period(void *arg)
{
    LARGE_INTEGER li;
    HANDLE timer;
    DWORD t, r;

    li.QuadPart = -1;

    timer = CreateWaitableTimerA(NULL, FALSE, NULL);
    ok(timer != NULL, "CreateWaitableTimer failed\n");

    t = GetTickCount();
    r = SetWaitableTimer(timer, &li, 3000, NULL, NULL, FALSE);
    ok(r, "SetWaitableTimer failed\n");

    r = WaitForSingleObject(timer, INFINITE);
175
    ok(r == WAIT_OBJECT_0, "WaitForSingleObject returned %ld\n", r);
176 177

    r = WaitForSingleObject(timer, INFINITE);
178
    ok(r == WAIT_OBJECT_0, "WaitForSingleObject returned %ld\n", r);
179 180
    CloseHandle(timer);
    t = GetTickCount() - t;
181
    ok(t > 2000, "t = %ld\n", t);
182 183 184 185 186 187 188 189 190 191
    return 0;
}

static DWORD WINAPI thread_SetTimer(void *arg)
{
    DWORD t = GetTickCount();
    UINT_PTR timer;
    MSG msg;

    timer = SetTimer(NULL, 0, 3000, NULL);
192
    ok(timer, "SetTimer failed (%ld)\n", GetLastError());
193 194 195 196 197 198 199 200

    while (GetMessageW(&msg, NULL, 0, 0))
    {
        DispatchMessageW(&msg);
        if (msg.message == WM_TIMER) break;
    }

    t = GetTickCount() - t;
201
    ok(t > 2000, "t = %ld\n", t);
202 203 204 205 206 207 208 209 210 211 212
    KillTimer(NULL, timer);
    return 0;
}

static void test_timeouts(void)
{
    HANDLE threads[7];
    DWORD i;

    if (!adjust_system_time(1))
    {
213
        skip("can't adjust system clock (%ld)\n", GetLastError());
214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
        return;
    }


    threads[0] = CreateThread(NULL, 0, thread_WaitForSingleObject, NULL, 0, NULL);
    threads[1] = CreateThread(NULL, 0, thread_Sleep, NULL, 0, NULL);
    threads[2] = CreateThread(NULL, 0, thread_SleepEx, NULL, 0, NULL);
    threads[3] = CreateThread(NULL, 0, thread_WaitableTimer_rel, NULL, 0, NULL);
    threads[4] = CreateThread(NULL, 0, thread_WaitableTimer_abs, NULL, 0, NULL);
    threads[5] = CreateThread(NULL, 0, thread_WaitableTimer_period, NULL, 0, NULL);
    threads[6] = CreateThread(NULL, 0, thread_SetTimer, NULL, 0, NULL);
    for(i=0; i<ARRAY_SIZE(threads); i++)
        ok(threads[i] != NULL, "CreateThread failed\n");

    Sleep(500);
    adjust_system_time(10);

    for (i=0; i<ARRAY_SIZE(threads); i++)
    {
        WaitForSingleObject(threads[i], INFINITE);
        CloseHandle(threads[i]);
    }
    adjust_system_time(-11);
}

Mike McCormack's avatar
Mike McCormack committed
239 240 241
START_TEST(timer)
{
    test_timer();
242
    test_timeouts();
Mike McCormack's avatar
Mike McCormack committed
243
}