Propagate the root folder's attributes to the registry.
[wine] / dlls / winmm / tests / timer.c
1 /*
2  * Test winmm timer
3  *
4  * Copyright (c) 2005 Robert Reif
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include <stdarg.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <math.h>
25
26 #include "wine/test.h"
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winnls.h"
30 #include "mmsystem.h"
31 #define NOBITMAP
32 #include "mmreg.h"
33
34 #include "winmm_test.h"
35
36 static TIMECAPS tc;
37
38 static void test_timeGetDevCaps(void)
39 {
40    MMRESULT rc;
41
42     rc = timeGetDevCaps(&tc, 0);
43     ok(rc == TIMERR_NOCANDO || rc == MMSYSERR_INVALPARAM,
44        "timeGetDevCaps() returned %s, should have returned TIMERR_NOCANDO "
45        "or MMSYSERR_INVALPARAM\n", mmsys_error(rc));
46
47     rc = timeGetDevCaps(0, sizeof(tc));
48     ok(rc == TIMERR_NOCANDO || rc == TIMERR_STRUCT,
49        "timeGetDevCaps() returned %s, should have returned TIMERR_NOCANDO "
50        "or TIMERR_STRUCT\n", mmsys_error(rc));
51
52     rc = timeGetDevCaps(0, 0);
53     ok(rc == TIMERR_NOCANDO || rc == MMSYSERR_INVALPARAM,
54        "timeGetDevCaps() returned %s, should have returned TIMERR_NOCANDO "
55        "or MMSYSERR_INVALPARAM\n", mmsys_error(rc));
56
57     rc = timeGetDevCaps(&tc, sizeof(tc));
58     ok(rc == TIMERR_NOERROR, "timeGetDevCaps() returned %s, "
59        "should have returned TIMERR_NOERROR\n", mmsys_error(rc));
60
61     if (rc == TIMERR_NOERROR)
62         trace("wPeriodMin = %u, wPeriodMax = %u\n",
63               tc.wPeriodMin, tc.wPeriodMax);
64 }
65
66 #define NUM_SAMPLES    100
67
68 static DWORD count = 0;
69 static DWORD times[NUM_SAMPLES];
70
71 static void CALLBACK testTimeProc(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
72 {
73     if (count < NUM_SAMPLES)
74         times[count++] = timeGetTime();
75 }
76
77 static void test_timer(UINT period, UINT resolution)
78 {
79     MMRESULT rc;
80     UINT i, id, delta;
81     DWORD dwMin = 0xffffffff, dwMax = 0;
82     double sum = 0.0;
83     double deviation = 0.0;
84
85     count = 0;
86
87     for (i = 0; i < NUM_SAMPLES; i++)
88         times[i] = 0;
89
90     rc = timeBeginPeriod(period);
91     ok(rc == TIMERR_NOERROR, "timeBeginPeriod(%u) returned %s, "
92        "should have returned TIMERR_NOERROR\n", period, mmsys_error(rc));
93     if (rc != TIMERR_NOERROR)
94         return;
95
96     id = timeSetEvent(period, resolution, testTimeProc, 0, TIME_PERIODIC);
97     ok(id != 0, "timeSetEvent(%u, %u, %p, 0, TIME_PERIODIC) returned %d, "
98        "should have returned id > 0\n", period, resolution, testTimeProc, id);
99     if (id == 0)
100         return;
101
102     Sleep((NUM_SAMPLES * period) + (2 * period));
103
104     rc = timeEndPeriod(period);
105     ok(rc == TIMERR_NOERROR, "timeEndPeriod(%u) returned %s, "
106        "should have returned TIMERR_NOERROR\n", period, mmsys_error(rc));
107     if (rc != TIMERR_NOERROR)
108         return;
109
110     rc = timeKillEvent(id);
111     ok(rc == TIMERR_NOERROR, "timeKillEvent(%u) returned %s, "
112        "should have returned TIMERR_NOERROR\n", id, mmsys_error(rc));
113
114     trace("period = %u, resolution = %u\n", period, resolution);
115
116     for (i = 0; i < count; i++)
117     {
118         if (i == 0)
119         {
120             if (winetest_debug > 1)
121                 trace("time[%d] = %lu\n", i, times[i]);
122         }
123         else
124         {
125             delta = times[i] - times[i - 1];
126
127             if (winetest_debug > 1)
128                 trace("time[%d] = %lu delta = %d\n", i, times[i], delta);
129
130             sum += delta;
131             deviation += ((delta - period) * (delta - period));
132
133             if (delta < dwMin)
134                 dwMin = delta;
135
136             if (delta > dwMax)
137                 dwMax = delta;
138         }
139     }
140
141     trace("min = %lu, max = %lu, average = %f, standard deviation = %f\n",
142           dwMin, dwMax, sum / (count - 1), sqrt(deviation / (count - 2)));
143 }
144
145 static const char * get_priority(int priority)
146 {
147     static char     tmp[32];
148 #define STR(x) case x: return #x
149     switch(priority) {
150     STR(THREAD_PRIORITY_LOWEST);
151     STR(THREAD_PRIORITY_BELOW_NORMAL);
152     STR(THREAD_PRIORITY_NORMAL);
153     STR(THREAD_PRIORITY_HIGHEST);
154     STR(THREAD_PRIORITY_ABOVE_NORMAL);
155     STR(THREAD_PRIORITY_TIME_CRITICAL);
156     STR(THREAD_PRIORITY_IDLE);
157     }
158     sprintf(tmp, "UNKNOWN(%d)", priority);
159     return tmp;
160 }
161
162 static int priority = 0;
163 static BOOL fired = FALSE;
164
165 static void CALLBACK priorityTimeProc(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
166 {
167     priority = GetThreadPriority(GetCurrentThread());
168     ok(priority!=THREAD_PRIORITY_ERROR_RETURN, "GetThreadPriority() failed, GetLastError() = %08lx\n", GetLastError());
169     fired = TRUE;
170 }
171
172 static void test_priority(void)
173 {
174     UINT id;
175
176     id = timeSetEvent(100, 100, priorityTimeProc, 0, TIME_ONESHOT);
177     ok(id != 0, "timeSetEvent(100, 100, %p, 0, TIME_ONESHOT) returned %d, "
178        "should have returned id > 0\n", priorityTimeProc, id);
179     if (id == 0)
180         return;
181
182     Sleep(200);
183
184     ok(fired == TRUE, "Callback not called\n");
185     if (fired)
186     {
187         ok(priority == THREAD_PRIORITY_TIME_CRITICAL,
188            "thread priority is %s, should be THREAD_PRIORITY_TIME_CRITICAL\n",
189            get_priority(priority));
190     }
191 }
192
193 START_TEST(timer)
194 {
195     test_timeGetDevCaps();
196
197     if (tc.wPeriodMin <= 1) {
198         test_timer(1, 0);
199         test_timer(1, 1);
200     }
201
202     if (tc.wPeriodMin <= 10) {
203         test_timer(10, 0);
204         test_timer(10, 1);
205         test_timer(10, 10);
206     }
207
208     if (tc.wPeriodMin <= 20) {
209         test_timer(20, 0);
210         test_timer(20, 1);
211         test_timer(20, 10);
212         test_timer(20, 20);
213     }
214
215     test_priority();
216 }