2 * System clock unit tests
4 * Copyright (C) 2007 Alex VillacĂs Lasso
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.
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.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "wine/test.h"
25 static ULONGLONG (WINAPI
*pGetTickCount64
)(void);
27 static BOOL
compare_time(REFERENCE_TIME x
, REFERENCE_TIME y
, unsigned int max_diff
)
29 REFERENCE_TIME diff
= x
> y
? x
- y
: y
- x
;
30 return diff
<= max_diff
;
33 static IReferenceClock
*create_system_clock(void)
35 IReferenceClock
*clock
= NULL
;
36 HRESULT hr
= CoCreateInstance(&CLSID_SystemClock
, NULL
, CLSCTX_INPROC_SERVER
,
37 &IID_IReferenceClock
, (void **)&clock
);
38 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
42 static ULONG
get_refcount(void *iface
)
44 IUnknown
*unknown
= iface
;
45 IUnknown_AddRef(unknown
);
46 return IUnknown_Release(unknown
);
49 #define check_interface(a, b, c) check_interface_(__LINE__, a, b, c)
50 static void check_interface_(unsigned int line
, void *iface_ptr
, REFIID iid
, BOOL supported
)
52 IUnknown
*iface
= iface_ptr
;
53 HRESULT hr
, expected_hr
;
56 expected_hr
= supported
? S_OK
: E_NOINTERFACE
;
58 hr
= IUnknown_QueryInterface(iface
, iid
, (void **)&unk
);
59 ok_(__FILE__
, line
)(hr
== expected_hr
, "Got hr %#x, expected %#x.\n", hr
, expected_hr
);
61 IUnknown_Release(unk
);
64 static void test_interfaces(void)
66 IReferenceClock
*clock
= create_system_clock();
69 check_interface(clock
, &IID_IReferenceClock
, TRUE
);
70 check_interface(clock
, &IID_IUnknown
, TRUE
);
72 check_interface(clock
, &IID_IDirectDraw
, FALSE
);
74 ref
= IReferenceClock_Release(clock
);
75 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
78 static const GUID test_iid
= {0x33333333};
79 static LONG outer_ref
= 1;
81 static HRESULT WINAPI
outer_QueryInterface(IUnknown
*iface
, REFIID iid
, void **out
)
83 if (IsEqualGUID(iid
, &IID_IUnknown
)
84 || IsEqualGUID(iid
, &IID_IReferenceClock
)
85 || IsEqualGUID(iid
, &test_iid
))
87 *out
= (IUnknown
*)0xdeadbeef;
90 ok(0, "unexpected call %s\n", wine_dbgstr_guid(iid
));
94 static ULONG WINAPI
outer_AddRef(IUnknown
*iface
)
96 return InterlockedIncrement(&outer_ref
);
99 static ULONG WINAPI
outer_Release(IUnknown
*iface
)
101 return InterlockedDecrement(&outer_ref
);
104 static const IUnknownVtbl outer_vtbl
=
106 outer_QueryInterface
,
111 static IUnknown test_outer
= {&outer_vtbl
};
113 static void test_aggregation(void)
115 IReferenceClock
*clock
, *clock2
;
116 IUnknown
*unk
, *unk2
;
120 clock
= (IReferenceClock
*)0xdeadbeef;
121 hr
= CoCreateInstance(&CLSID_SystemClock
, &test_outer
, CLSCTX_INPROC_SERVER
,
122 &IID_IReferenceClock
, (void **)&clock
);
123 ok(hr
== E_NOINTERFACE
, "Got hr %#x.\n", hr
);
124 ok(!clock
, "Got interface %p.\n", clock
);
126 hr
= CoCreateInstance(&CLSID_SystemClock
, &test_outer
, CLSCTX_INPROC_SERVER
,
127 &IID_IUnknown
, (void **)&unk
);
128 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
129 ok(outer_ref
== 1, "Got unexpected refcount %d.\n", outer_ref
);
130 ok(unk
!= &test_outer
, "Returned IUnknown should not be outer IUnknown.\n");
131 ref
= get_refcount(unk
);
132 ok(ref
== 1, "Got unexpected refcount %d.\n", ref
);
134 ref
= IUnknown_AddRef(unk
);
135 ok(ref
== 2, "Got unexpected refcount %d.\n", ref
);
136 ok(outer_ref
== 1, "Got unexpected refcount %d.\n", outer_ref
);
138 ref
= IUnknown_Release(unk
);
139 ok(ref
== 1, "Got unexpected refcount %d.\n", ref
);
140 ok(outer_ref
== 1, "Got unexpected refcount %d.\n", outer_ref
);
142 hr
= IUnknown_QueryInterface(unk
, &IID_IUnknown
, (void **)&unk2
);
143 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
144 ok(unk2
== unk
, "Got unexpected IUnknown %p.\n", unk2
);
145 IUnknown_Release(unk2
);
147 hr
= IUnknown_QueryInterface(unk
, &IID_IReferenceClock
, (void **)&clock
);
148 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
150 hr
= IReferenceClock_QueryInterface(clock
, &IID_IUnknown
, (void **)&unk2
);
151 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
152 ok(unk2
== (IUnknown
*)0xdeadbeef, "Got unexpected IUnknown %p.\n", unk2
);
154 hr
= IReferenceClock_QueryInterface(clock
, &IID_IReferenceClock
, (void **)&clock2
);
155 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
156 ok(clock2
== (IReferenceClock
*)0xdeadbeef, "Got unexpected IReferenceClock %p.\n", clock2
);
158 hr
= IUnknown_QueryInterface(unk
, &test_iid
, (void **)&unk2
);
159 ok(hr
== E_NOINTERFACE
, "Got hr %#x.\n", hr
);
160 ok(!unk2
, "Got unexpected IUnknown %p.\n", unk2
);
162 hr
= IReferenceClock_QueryInterface(clock
, &test_iid
, (void **)&unk2
);
163 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
164 ok(unk2
== (IUnknown
*)0xdeadbeef, "Got unexpected IUnknown %p.\n", unk2
);
166 IReferenceClock_Release(clock
);
167 ref
= IUnknown_Release(unk
);
168 ok(!ref
, "Got unexpected refcount %d.\n", ref
);
169 ok(outer_ref
== 1, "Got unexpected refcount %d.\n", outer_ref
);
172 static void test_get_time(void)
174 IReferenceClock
*clock
= create_system_clock();
175 REFERENCE_TIME time1
, time2
;
179 hr
= IReferenceClock_GetTime(clock
, NULL
);
180 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
182 hr
= IReferenceClock_GetTime(clock
, &time1
);
184 time2
= pGetTickCount64() * 10000;
186 time2
= (REFERENCE_TIME
)GetTickCount() * 10000;
187 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
188 ok(time1
% 10000 == 0, "Expected no less than 1ms coarseness, but got time %s.\n",
189 wine_dbgstr_longlong(time1
));
190 ok(compare_time(time1
, time2
, 20 * 10000), "Expected about %s, got %s.\n",
191 wine_dbgstr_longlong(time2
), wine_dbgstr_longlong(time1
));
193 hr
= IReferenceClock_GetTime(clock
, &time2
);
194 ok(hr
== (time2
== time1
? S_FALSE
: S_OK
), "Got hr %#x.\n", hr
);
197 hr
= IReferenceClock_GetTime(clock
, &time2
);
198 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
199 ok(time2
- time1
> 80 * 10000, "Expected about %s, but got %s.\n",
200 wine_dbgstr_longlong(time1
+ 80 * 10000), wine_dbgstr_longlong(time2
));
202 ref
= IReferenceClock_Release(clock
);
203 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
206 static void test_advise(void)
208 IReferenceClock
*clock
= create_system_clock();
209 HANDLE event
, semaphore
;
210 REFERENCE_TIME current
;
216 event
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
217 semaphore
= CreateSemaphoreA(NULL
, 0, 10, NULL
);
219 hr
= IReferenceClock_GetTime(clock
, ¤t
);
220 ok(SUCCEEDED(hr
), "Got hr %#x.\n", hr
);
222 hr
= IReferenceClock_AdviseTime(clock
, current
, 500 * 10000, (HEVENT
)event
, NULL
);
223 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
225 hr
= IReferenceClock_AdviseTime(clock
, -1000 * 10000, 500 * 10000, (HEVENT
)event
, &cookie
);
226 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
228 hr
= IReferenceClock_AdviseTime(clock
, current
, 500 * 10000, (HEVENT
)event
, &cookie
);
229 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
230 ok(WaitForSingleObject(event
, 460) == WAIT_TIMEOUT
, "Event should not be signaled.\n");
231 ok(!WaitForSingleObject(event
, 80), "Event should be signaled.\n");
233 hr
= IReferenceClock_Unadvise(clock
, cookie
);
234 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
237 hr
= IReferenceClock_GetTime(clock
, ¤t
);
238 ok(SUCCEEDED(hr
), "Got hr %#x.\n", hr
);
239 hr
= IReferenceClock_AdviseTime(clock
, current
, 500 * 10000, (HEVENT
)event
, &cookie
);
240 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
241 hr
= IReferenceClock_Unadvise(clock
, cookie
);
242 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
243 ok(WaitForSingleObject(event
, 540) == WAIT_TIMEOUT
, "Event should not be signaled.\n");
246 hr
= IReferenceClock_GetTime(clock
, ¤t
);
247 ok(SUCCEEDED(hr
), "Got hr %#x.\n", hr
);
248 hr
= IReferenceClock_AdviseTime(clock
, current
+ 500 * 10000, 0, (HEVENT
)event
, &cookie
);
249 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
250 ok(WaitForSingleObject(event
, 460) == WAIT_TIMEOUT
, "Event should not be signaled.\n");
251 ok(!WaitForSingleObject(event
, 80), "Event should be signaled.\n");
253 hr
= IReferenceClock_GetTime(clock
, ¤t
);
254 ok(SUCCEEDED(hr
), "Got hr %#x.\n", hr
);
256 hr
= IReferenceClock_AdvisePeriodic(clock
, current
, 500 * 10000, (HSEMAPHORE
)semaphore
, NULL
);
257 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
259 hr
= IReferenceClock_AdvisePeriodic(clock
, current
, 0, (HSEMAPHORE
)semaphore
, &cookie
);
260 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
262 hr
= IReferenceClock_AdvisePeriodic(clock
, current
, -500 * 10000, (HSEMAPHORE
)semaphore
, &cookie
);
263 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
265 hr
= IReferenceClock_AdvisePeriodic(clock
, -500 * 10000, 1000 * 10000, (HSEMAPHORE
)semaphore
, &cookie
);
266 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
268 hr
= IReferenceClock_AdvisePeriodic(clock
, current
, 100 * 10000, (HSEMAPHORE
)semaphore
, &cookie
);
269 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
270 ok(!WaitForSingleObject(semaphore
, 50), "Semaphore should be signaled.\n");
271 for (i
= 0; i
< 5; ++i
)
272 ok(!WaitForSingleObject(semaphore
, 500), "Semaphore should be signaled.\n");
274 hr
= IReferenceClock_Unadvise(clock
, cookie
);
275 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
276 ok(WaitForSingleObject(semaphore
, 200) == WAIT_TIMEOUT
, "Semaphore should not be signaled.\n");
279 CloseHandle(semaphore
);
281 ref
= IReferenceClock_Release(clock
);
282 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
285 START_TEST(systemclock
)
289 pGetTickCount64
= (void *)GetProcAddress(GetModuleHandleA("kernel32.dll"), "GetTickCount64");