2 * Copyright (C) 2005 Wim Taymans <wim@fluendo.com>
4 * gstsystemclock.c: Unit test for GstSystemClock
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 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 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
22 #include <gst/check/gstcheck.h>
24 /* see if the defines make sense */
25 GST_START_TEST (test_range)
27 GstClockTime time, time2;
30 fail_unless (time == G_GUINT64_CONSTANT (1000000000));
33 fail_unless (time2 == 1000000);
34 fail_unless (time2 == GST_MSECOND);
35 fail_unless (time2 == GST_TIME_AS_USECONDS (time));
37 time2 = time / 1000000;
38 fail_unless (time2 == 1000);
39 fail_unless (time2 == GST_USECOND);
40 fail_unless (time2 == GST_TIME_AS_MSECONDS (time));
45 GST_START_TEST (test_signedness)
47 GstClockTime time[] = { 0, 1, G_MAXUINT64 / GST_SECOND };
48 GstClockTimeDiff diff[] =
49 { 0, 1, -1, G_MAXINT64 / GST_SECOND, G_MININT64 / GST_SECOND };
52 for (i = 0; i < G_N_ELEMENTS (time); i++) {
53 fail_if (time[i] != (time[i] * GST_SECOND / GST_SECOND));
55 for (i = 0; i < G_N_ELEMENTS (diff); i++) {
56 fail_if (diff[i] != (diff[i] * GST_SECOND / GST_SECOND));
62 #define TIME_UNIT (GST_SECOND / 5)
64 gst_clock_debug (GstClock * clock)
68 time = gst_clock_get_time (clock);
69 GST_DEBUG ("Clock info: time %" GST_TIME_FORMAT, GST_TIME_ARGS (time));
73 ok_callback (GstClock * clock, GstClockTime time,
74 GstClockID id, gpointer user_data)
76 GST_LOG ("unlocked async id %p", id);
81 error_callback (GstClock * clock, GstClockTime time,
82 GstClockID id, gpointer user_data)
84 GST_WARNING ("unlocked unscheduled async id %p, this is wrong", id);
91 store_callback (GstClock * clock, GstClockTime time,
92 GstClockID id, gpointer user_data)
94 GList **list = user_data;
96 GST_DEBUG ("unlocked async id %p", id);
97 *list = g_list_append (*list, id);
102 notify_callback (GstClock * clock, GstClockTime time,
103 GstClockID id, gpointer user_data)
105 gboolean *ret = (gboolean *) user_data;
113 GST_START_TEST (test_single_shot)
118 GstClockReturn result;
120 clock = gst_system_clock_obtain ();
121 fail_unless (clock != NULL, "Could not create instance of GstSystemClock");
123 gst_clock_debug (clock);
124 base = gst_clock_get_time (clock);
126 id = gst_clock_new_single_shot_id (clock, base + TIME_UNIT);
127 fail_unless (id != NULL, "Could not create single shot id");
129 GST_DEBUG ("waiting one time unit");
130 result = gst_clock_id_wait (id, NULL);
131 gst_clock_debug (clock);
132 fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK (result=%d)",
134 fail_unless (gst_clock_get_time (clock) > (base + TIME_UNIT),
135 "target time has not been reached");
137 GST_DEBUG ("waiting in the past");
138 result = gst_clock_id_wait (id, NULL);
139 gst_clock_debug (clock);
140 fail_unless (result == GST_CLOCK_EARLY,
141 "Waiting did not return EARLY(result=%d)", result);
142 gst_clock_id_unref (id);
144 id = gst_clock_new_single_shot_id (clock, base + 2 * TIME_UNIT);
145 GST_DEBUG ("waiting one second async id %p", id);
146 result = gst_clock_id_wait_async (id, ok_callback, NULL);
147 gst_clock_id_unref (id);
148 fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
149 g_usleep (TIME_UNIT / (2 * 1000));
151 id = gst_clock_new_single_shot_id (clock, base + 5 * TIME_UNIT);
152 GST_DEBUG ("waiting one second async, with cancel on id %p", id);
153 result = gst_clock_id_wait_async (id, error_callback, NULL);
154 fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
155 g_usleep (TIME_UNIT / (2 * 1000));
156 GST_DEBUG ("cancel id %p after half a time unit", id);
157 gst_clock_id_unschedule (id);
158 gst_clock_id_unref (id);
159 GST_DEBUG ("canceled id %p", id);
161 GST_DEBUG ("waiting multiple one second async, with cancel");
162 id = gst_clock_new_single_shot_id (clock, base + 5 * TIME_UNIT);
163 id2 = gst_clock_new_single_shot_id (clock, base + 6 * TIME_UNIT);
164 GST_DEBUG ("waiting id %p", id);
165 result = gst_clock_id_wait_async (id, ok_callback, NULL);
166 fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
167 gst_clock_id_unref (id);
168 GST_DEBUG ("waiting id %p", id2);
169 result = gst_clock_id_wait_async (id2, error_callback, NULL);
170 fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
171 g_usleep (TIME_UNIT / (2 * 1000));
172 GST_DEBUG ("cancel id %p after half a time unit", id2);
173 gst_clock_id_unschedule (id2);
174 GST_DEBUG ("canceled id %p", id2);
175 gst_clock_id_unref (id2);
176 g_usleep (TIME_UNIT / (2 * 1000));
181 GST_START_TEST (test_periodic_shot)
186 GstClockReturn result;
188 clock = gst_system_clock_obtain ();
189 fail_unless (clock != NULL, "Could not create instance of GstSystemClock");
191 gst_clock_debug (clock);
192 base = gst_clock_get_time (clock);
194 /* signal every half a time unit */
195 id = gst_clock_new_periodic_id (clock, base + TIME_UNIT, TIME_UNIT / 2);
196 fail_unless (id != NULL, "Could not create periodic id");
198 GST_DEBUG ("waiting one time unit");
199 result = gst_clock_id_wait (id, NULL);
200 gst_clock_debug (clock);
201 fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
203 GST_DEBUG ("waiting for the next");
204 result = gst_clock_id_wait (id, NULL);
205 gst_clock_debug (clock);
206 fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
208 GST_DEBUG ("waiting for the next async %p", id);
209 result = gst_clock_id_wait_async (id, ok_callback, NULL);
210 fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
211 g_usleep (TIME_UNIT / (2 * 1000));
213 GST_DEBUG ("waiting some more for the next async %p", id);
214 result = gst_clock_id_wait_async (id, ok_callback, NULL);
215 fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
216 g_usleep (TIME_UNIT / (2 * 1000));
218 id2 = gst_clock_new_periodic_id (clock, base + TIME_UNIT, TIME_UNIT / 2);
219 fail_unless (id2 != NULL, "Could not create second periodic id");
221 GST_DEBUG ("waiting some more for another async %p", id2);
222 result = gst_clock_id_wait_async (id2, ok_callback, NULL);
223 fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
224 g_usleep (TIME_UNIT / (2 * 1000));
226 GST_DEBUG ("unschedule %p", id);
227 gst_clock_id_unschedule (id);
229 /* entry cannot be used again */
230 result = gst_clock_id_wait_async (id, error_callback, NULL);
231 fail_unless (result == GST_CLOCK_UNSCHEDULED,
232 "Waiting did not return UNSCHEDULED");
233 result = gst_clock_id_wait (id, NULL);
234 fail_unless (result == GST_CLOCK_UNSCHEDULED,
235 "Waiting did not return UNSCHEDULED");
236 g_usleep (TIME_UNIT / (2 * 1000));
239 gst_clock_id_unref (id);
244 GST_START_TEST (test_async_order)
248 GList *cb_list = NULL, *next;
250 GstClockReturn result;
252 clock = gst_system_clock_obtain ();
253 fail_unless (clock != NULL, "Could not create instance of GstSystemClock");
255 gst_clock_debug (clock);
256 base = gst_clock_get_time (clock);
258 id1 = gst_clock_new_single_shot_id (clock, base + 2 * TIME_UNIT);
259 id2 = gst_clock_new_single_shot_id (clock, base + 1 * TIME_UNIT);
260 result = gst_clock_id_wait_async (id1, store_callback, &cb_list);
261 fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
262 g_usleep (TIME_UNIT / (2 * 1000));
263 result = gst_clock_id_wait_async (id2, store_callback, &cb_list);
264 fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
265 g_usleep (TIME_UNIT / 1000);
266 /* at this point at least one of the timers should have timed out */
267 fail_unless (cb_list != NULL, "expected notification");
268 fail_unless (cb_list->data == id2,
269 "Expected notification for id2 to come first");
270 g_usleep (TIME_UNIT / 1000);
271 /* now both should have timed out */
272 next = g_list_next (cb_list);
273 fail_unless (next != NULL, "expected second notification");
274 fail_unless (next->data == id1, "Missing notification for id1");
275 gst_clock_id_unref (id1);
276 gst_clock_id_unref (id2);
277 g_list_free (cb_list);
282 GST_START_TEST (test_periodic_multi)
287 GstClockReturn result;
288 gboolean got_callback = FALSE;
290 clock = gst_system_clock_obtain ();
291 fail_unless (clock != NULL, "Could not create instance of GstSystemClock");
293 gst_clock_debug (clock);
294 base = gst_clock_get_time (clock);
296 clock_id = gst_clock_new_periodic_id (clock, base + TIME_UNIT, TIME_UNIT);
297 gst_clock_id_wait (clock_id, NULL);
298 fail_unless (gst_clock_get_time (clock) >= base + TIME_UNIT);
299 fail_unless (gst_clock_get_time (clock) < base + 2 * TIME_UNIT);
301 /* now perform a concurrent wait and wait_async */
303 result = gst_clock_id_wait_async (clock_id, notify_callback, &got_callback);
304 fail_unless (result == GST_CLOCK_OK, "Async waiting did not return OK");
305 fail_unless (got_callback == FALSE);
306 result = gst_clock_id_wait (clock_id, NULL);
307 fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
308 fail_unless (gst_clock_get_time (clock) >= base + 2 * TIME_UNIT);
309 /* give the async thread some time to call our callback: */
310 g_usleep (TIME_UNIT / (10 * 1000));
311 fail_unless (got_callback == TRUE, "got no async callback (1)");
312 fail_unless (gst_clock_get_time (clock) < base + 3 * TIME_UNIT);
313 got_callback = FALSE;
315 result = gst_clock_id_wait (clock_id, NULL);
316 fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
317 fail_unless (gst_clock_get_time (clock) >= base + 3 * TIME_UNIT);
318 /* give the async thread some time to call our callback: */
319 g_usleep (TIME_UNIT / (10 * 1000));
320 fail_unless (got_callback == TRUE, "got no async callback (2)");
321 fail_unless (gst_clock_get_time (clock) < base + 4 * TIME_UNIT);
326 GST_START_TEST (test_diff)
328 GstClockTime time1[] = { 0, (GstClockTime) - 1, 0, 1, 2 * GST_SECOND,
329 (GstClockTime) - GST_SECOND, (GstClockTime) - GST_SECOND
331 GstClockTime time2[] =
332 { 0, 1, 1, 0, 1 * GST_SECOND, (GstClockTime) - GST_SECOND, GST_SECOND };
333 GstClockTimeDiff d[] = { 0, 2, 1, -1, -GST_SECOND, 0, 2 * GST_SECOND };
336 for (i = 0; i < G_N_ELEMENTS (d); i++) {
337 fail_if (d[i] != GST_CLOCK_DIFF (time1[i], time2[i]));
343 /* test if a blocking wait, unblocked by an async entry continues to be
349 GstClockTimeDiff jitter;
354 mixed_thread (MixedInfo * info)
356 info->ret = gst_clock_id_wait (info->id, &info->jitter);
361 mixed_async_cb (GstClock * clock, GstClockTime time,
362 GstClockID id, gpointer user_data)
367 GST_START_TEST (test_mixed)
370 GError *error = NULL;
375 info.clock = gst_system_clock_obtain ();
376 fail_unless (info.clock != NULL,
377 "Could not create instance of GstSystemClock");
379 /* get current time of the clock as base time */
380 base = gst_clock_get_time (info.clock);
382 /* create entry to wait for 1 second */
383 info.id = gst_clock_new_single_shot_id (info.clock, base + GST_SECOND);
385 /* make and start an entry that is scheduled every 10ms */
386 id = gst_clock_new_periodic_id (info.clock, base, 10 * GST_MSECOND);
388 /* start waiting for the entry */
389 thread = g_thread_create ((GThreadFunc) mixed_thread, &info, TRUE, &error);
390 fail_unless (error == NULL, "error creating thread");
391 fail_unless (thread != NULL, "Could not create thread");
393 /* wait half a second so we are sure to be in the thread */
394 g_usleep (G_USEC_PER_SEC / 2);
396 /* start scheduling the entry */
397 gst_clock_id_wait_async (id, mixed_async_cb, NULL);
399 /* wait for thread to finish */
400 g_thread_join (thread);
401 /* entry must have timed out correctly */
402 fail_unless (info.ret == GST_CLOCK_OK, "clock return was %d", info.ret);
404 gst_clock_id_unschedule (id);
405 gst_clock_id_unref (id);
406 gst_clock_id_unref (info.id);
407 gst_object_unref (info.clock);
413 gst_systemclock_suite (void)
415 Suite *s = suite_create ("GstSystemClock");
416 TCase *tc_chain = tcase_create ("waiting");
418 suite_add_tcase (s, tc_chain);
419 tcase_add_test (tc_chain, test_range);
420 tcase_add_test (tc_chain, test_signedness);
421 tcase_add_test (tc_chain, test_single_shot);
422 tcase_add_test (tc_chain, test_periodic_shot);
423 tcase_add_test (tc_chain, test_periodic_multi);
424 tcase_add_test (tc_chain, test_async_order);
425 tcase_add_test (tc_chain, test_diff);
426 tcase_add_test (tc_chain, test_mixed);
431 GST_CHECK_MAIN (gst_systemclock);