2 * Copyright (C) 2005 Jan Schmidt <thaytan@mad.scientist.com>
4 * gstevent.c: Unit test for event handling
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.
23 #include <gst/check/gstcheck.h>
25 GST_START_TEST (create_events)
27 GstEvent *event, *event2;
28 GstStructure *structure;
32 event = gst_event_new_flush_start ();
33 fail_if (event == NULL);
34 fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_START);
35 fail_unless (GST_EVENT_IS_UPSTREAM (event));
36 fail_unless (GST_EVENT_IS_DOWNSTREAM (event));
37 fail_if (GST_EVENT_IS_SERIALIZED (event));
38 gst_event_unref (event);
42 event = gst_event_new_flush_stop ();
43 fail_if (event == NULL);
44 fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP);
45 fail_unless (GST_EVENT_IS_UPSTREAM (event));
46 fail_unless (GST_EVENT_IS_DOWNSTREAM (event));
47 fail_unless (GST_EVENT_IS_SERIALIZED (event));
48 gst_event_unref (event);
52 event = gst_event_new_eos ();
53 fail_if (event == NULL);
54 fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_EOS);
55 fail_if (GST_EVENT_IS_UPSTREAM (event));
56 fail_unless (GST_EVENT_IS_DOWNSTREAM (event));
57 fail_unless (GST_EVENT_IS_SERIALIZED (event));
58 gst_event_unref (event);
62 gdouble rate, applied_rate;
64 gint64 start, end, base;
68 gst_event_new_new_segment (FALSE, 0.5, 1.0, GST_FORMAT_TIME, 1,
69 G_MAXINT64, 0xdeadbeef);
70 fail_if (event == NULL);
71 fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT);
72 fail_if (GST_EVENT_IS_UPSTREAM (event));
73 fail_unless (GST_EVENT_IS_DOWNSTREAM (event));
74 fail_unless (GST_EVENT_IS_SERIALIZED (event));
76 gst_event_parse_new_segment (event, &update, &rate, &applied_rate, &format,
78 fail_unless (update == FALSE);
79 fail_unless (rate == 0.5);
80 fail_unless (applied_rate == 1.0);
81 fail_unless (format == GST_FORMAT_TIME);
82 fail_unless (start == 1);
83 fail_unless (end == G_MAXINT64);
84 fail_unless (base == 0xdeadbeef);
86 /* Check that the new segment was created with applied_rate of 1.0 */
87 gst_event_parse_new_segment (event, &update, &rate, &applied_rate,
88 &format, &start, &end, &base);
90 fail_unless (update == FALSE);
91 fail_unless (rate == 0.5);
92 fail_unless (applied_rate == 1.0);
93 fail_unless (format == GST_FORMAT_TIME);
94 fail_unless (start == 1);
95 fail_unless (end == G_MAXINT64);
97 gst_event_unref (event);
100 gst_event_new_new_segment (TRUE, 0.75, 0.5, GST_FORMAT_BYTES, 0,
101 G_MAXINT64 - 1, 0xdeadbeef);
103 fail_if (event == NULL);
104 fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT);
105 fail_if (GST_EVENT_IS_UPSTREAM (event));
106 fail_unless (GST_EVENT_IS_DOWNSTREAM (event));
107 fail_unless (GST_EVENT_IS_SERIALIZED (event));
109 gst_event_parse_new_segment (event, &update, &rate, &applied_rate,
110 &format, &start, &end, &base);
112 fail_unless (update == TRUE);
113 fail_unless (rate == 0.75);
114 fail_unless (applied_rate == 0.5);
115 fail_unless (format == GST_FORMAT_BYTES);
116 fail_unless (start == 0);
117 fail_unless (end == (G_MAXINT64 - 1));
119 gst_event_unref (event);
124 GstTagList *taglist = gst_tag_list_new ();
125 GstTagList *tl2 = NULL;
127 event = gst_event_new_tag (taglist);
128 fail_if (taglist == NULL);
129 fail_if (event == NULL);
130 fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_TAG);
131 fail_if (GST_EVENT_IS_UPSTREAM (event));
132 fail_unless (GST_EVENT_IS_DOWNSTREAM (event));
133 fail_unless (GST_EVENT_IS_SERIALIZED (event));
135 gst_event_parse_tag (event, &tl2);
136 fail_unless (taglist == tl2);
137 gst_event_unref (event);
142 GstQOSType t1 = GST_QOS_TYPE_THROTTLE, t2;
143 gdouble p1 = 1.0, p2;
144 GstClockTimeDiff ctd1 = G_GINT64_CONSTANT (10), ctd2;
145 GstClockTime ct1 = G_GUINT64_CONSTANT (20), ct2;
147 event = gst_event_new_qos (t1, p1, ctd1, ct1);
148 fail_if (event == NULL);
149 fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_QOS);
150 fail_unless (GST_EVENT_IS_UPSTREAM (event));
151 fail_if (GST_EVENT_IS_DOWNSTREAM (event));
152 fail_if (GST_EVENT_IS_SERIALIZED (event));
154 gst_event_parse_qos (event, &t2, &p2, &ctd2, &ct2);
155 fail_unless (p1 == p2);
156 fail_unless (ctd1 == ctd2);
157 fail_unless (ct1 == ct2);
158 gst_event_parse_qos (event, &t2, &p2, &ctd2, &ct2);
159 fail_unless (t2 == GST_QOS_TYPE_THROTTLE);
160 fail_unless (p1 == p2);
161 fail_unless (ctd1 == ctd2);
162 fail_unless (ct1 == ct2);
163 gst_event_unref (event);
165 ctd1 = G_GINT64_CONSTANT (-10);
166 event = gst_event_new_qos (t1, p1, ctd1, ct1);
167 gst_event_parse_qos (event, &t2, &p2, &ctd2, &ct2);
168 fail_unless (t2 == GST_QOS_TYPE_THROTTLE);
169 gst_event_unref (event);
171 event = gst_event_new_qos (t1, p1, ctd1, ct1);
172 gst_event_parse_qos (event, &t2, &p2, &ctd2, &ct2);
173 fail_unless (t2 == GST_QOS_TYPE_THROTTLE);
174 fail_unless (p1 == p2);
175 fail_unless (ctd1 == ctd2);
176 fail_unless (ct1 == ct2);
177 gst_event_unref (event);
185 GstSeekType cur_type, stop_type;
188 event = gst_event_new_seek (0.5, GST_FORMAT_BYTES,
189 GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE,
190 GST_SEEK_TYPE_SET, 1, GST_SEEK_TYPE_NONE, 0xdeadbeef);
192 fail_if (event == NULL);
193 fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_SEEK);
194 fail_unless (GST_EVENT_IS_UPSTREAM (event));
195 fail_if (GST_EVENT_IS_DOWNSTREAM (event));
196 fail_if (GST_EVENT_IS_SERIALIZED (event));
198 gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
200 fail_unless (rate == 0.5);
201 fail_unless (format == GST_FORMAT_BYTES);
202 fail_unless (flags == (GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE));
203 fail_unless (cur_type == GST_SEEK_TYPE_SET);
204 fail_unless (cur == 1);
205 fail_unless (stop_type == GST_SEEK_TYPE_NONE);
206 fail_unless (stop == 0xdeadbeef);
208 gst_event_unref (event);
213 structure = gst_structure_new ("application/x-gst-navigation", "event",
214 G_TYPE_STRING, "key-press", "key", G_TYPE_STRING, "mon", NULL);
215 fail_if (structure == NULL);
216 event = gst_event_new_navigation (structure);
217 fail_if (event == NULL);
218 fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_NAVIGATION);
219 fail_unless (GST_EVENT_IS_UPSTREAM (event));
220 fail_if (GST_EVENT_IS_DOWNSTREAM (event));
221 fail_if (GST_EVENT_IS_SERIALIZED (event));
223 fail_unless (gst_event_get_structure (event) == structure);
224 gst_event_unref (event);
227 /* Custom event types */
229 structure = gst_structure_empty_new ("application/x-custom");
230 fail_if (structure == NULL);
231 event = gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, structure);
232 fail_if (event == NULL);
233 fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_UPSTREAM);
234 fail_unless (GST_EVENT_IS_UPSTREAM (event));
235 fail_if (GST_EVENT_IS_DOWNSTREAM (event));
236 fail_if (GST_EVENT_IS_SERIALIZED (event));
237 fail_unless (gst_event_get_structure (event) == structure);
238 fail_unless (gst_event_has_name (event, "application/x-custom"));
239 gst_event_unref (event);
241 /* Decided not to test the other custom enum types, as they
242 * only differ by the value of the enum passed to gst_event_new_custom
248 structure = gst_structure_empty_new ("application/x-custom");
249 fail_if (structure == NULL);
250 event = gst_event_new_custom (GST_EVENT_CUSTOM_BOTH, structure);
252 fail_if (event == NULL);
253 event2 = gst_event_copy (event);
254 fail_if (event2 == NULL);
255 fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_TYPE (event2));
256 fail_unless (gst_event_has_name (event, "application/x-custom"));
258 /* The structure should have been duplicated */
259 fail_if (gst_event_get_structure (event) ==
260 gst_event_get_structure (event2));
262 gst_event_unref (event);
263 gst_event_unref (event2);
266 /* Make events writable */
268 structure = gst_structure_empty_new ("application/x-custom");
269 fail_if (structure == NULL);
270 event = gst_event_new_custom (GST_EVENT_CUSTOM_BOTH, structure);
271 /* ref the event so that it becomes non-writable */
272 gst_event_ref (event);
273 gst_event_ref (event);
274 /* this should fail if the structure isn't writable */
275 ASSERT_CRITICAL (gst_structure_remove_all_fields ((GstStructure *)
276 gst_event_get_structure (event)));
277 fail_unless (gst_event_has_name (event, "application/x-custom"));
279 /* now make writable */
281 GST_EVENT (gst_mini_object_make_writable (GST_MINI_OBJECT (event)));
282 fail_unless (event != event2);
283 /* this fail if the structure isn't writable */
284 gst_structure_remove_all_fields ((GstStructure *)
285 gst_event_get_structure (event2));
286 fail_unless (gst_event_has_name (event2, "application/x-custom"));
288 gst_event_unref (event);
289 gst_event_unref (event);
290 gst_event_unref (event2);
296 static GTimeVal sent_event_time;
297 static GstEvent *got_event_before_q, *got_event_after_q;
298 static GTimeVal got_event_time;
301 event_probe (GstPad * pad, GstMiniObject ** data, gpointer user_data)
303 gboolean before_q = (gboolean) GPOINTER_TO_INT (user_data);
305 fail_unless (GST_IS_EVENT (data));
307 GST_DEBUG ("event probe called");
310 switch (GST_EVENT_TYPE (GST_EVENT (data))) {
311 case GST_EVENT_CUSTOM_UPSTREAM:
312 case GST_EVENT_CUSTOM_BOTH:
313 case GST_EVENT_CUSTOM_BOTH_OOB:
314 if (got_event_before_q != NULL)
316 gst_event_ref ((GstEvent *) data);
317 g_get_current_time (&got_event_time);
318 got_event_before_q = GST_EVENT (data);
324 switch (GST_EVENT_TYPE (GST_EVENT (data))) {
325 case GST_EVENT_CUSTOM_DOWNSTREAM:
326 case GST_EVENT_CUSTOM_DOWNSTREAM_OOB:
327 case GST_EVENT_CUSTOM_BOTH:
328 case GST_EVENT_CUSTOM_BOTH_OOB:
329 if (got_event_after_q != NULL)
331 gst_event_ref ((GstEvent *) data);
332 g_get_current_time (&got_event_time);
333 got_event_after_q = GST_EVENT (data);
343 static void test_event
344 (GstBin * pipeline, GstEventType type, GstPad * pad,
345 gboolean expect_before_q, GstPad * fake_srcpad)
351 got_event_before_q = got_event_after_q = NULL;
353 gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
354 gst_element_get_state (GST_ELEMENT (pipeline), NULL, NULL,
355 GST_CLOCK_TIME_NONE);
357 GST_DEBUG ("test event called");
359 event = gst_event_new_custom (type,
360 gst_structure_empty_new ("application/x-custom"));
361 g_get_current_time (&sent_event_time);
362 got_event_time.tv_sec = 0;
363 got_event_time.tv_usec = 0;
365 /* We block the pad so the stream lock is released and we can send the event */
366 fail_unless (gst_pad_set_blocked (fake_srcpad, TRUE) == TRUE);
368 /* We send on the peer pad, since the pad is blocked */
369 fail_unless ((peer = gst_pad_get_peer (pad)) != NULL);
370 gst_pad_send_event (peer, event);
371 gst_object_unref (peer);
373 fail_unless (gst_pad_set_blocked (fake_srcpad, FALSE) == TRUE);
375 if (expect_before_q) {
376 /* Wait up to 5 seconds for the event to appear */
377 for (i = 0; i < 500; i++) {
378 g_usleep (G_USEC_PER_SEC / 100);
379 if (got_event_before_q != NULL)
382 fail_if (got_event_before_q == NULL,
383 "Expected event failed to appear upstream of the queue "
385 fail_unless (GST_EVENT_TYPE (got_event_before_q) == type);
387 /* Wait up to 10 seconds for the event to appear */
388 for (i = 0; i < 1000; i++) {
389 g_usleep (G_USEC_PER_SEC / 100);
390 if (got_event_after_q != NULL)
393 fail_if (got_event_after_q == NULL,
394 "Expected event failed to appear after the queue within 10 seconds");
395 fail_unless (GST_EVENT_TYPE (got_event_after_q) == type);
398 gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PAUSED);
399 gst_element_get_state (GST_ELEMENT (pipeline), NULL, NULL,
400 GST_CLOCK_TIME_NONE);
402 if (got_event_before_q)
403 gst_event_unref (got_event_before_q);
404 if (got_event_after_q)
405 gst_event_unref (got_event_after_q);
407 got_event_before_q = got_event_after_q = NULL;
411 timediff (GTimeVal * end, GTimeVal * start)
413 return (end->tv_sec - start->tv_sec) * G_USEC_PER_SEC +
414 (end->tv_usec - start->tv_usec);
417 GST_START_TEST (send_custom_events)
419 /* Run some tests on custom events. Checking for serialisation and whatnot.
420 * pipeline is fakesrc ! queue ! fakesink */
422 GstElement *fakesrc, *fakesink, *queue;
423 GstPad *srcpad, *sinkpad;
425 fail_if ((pipeline = (GstBin *) gst_pipeline_new ("testpipe")) == NULL);
426 fail_if ((fakesrc = gst_element_factory_make ("fakesrc", NULL)) == NULL);
427 fail_if ((fakesink = gst_element_factory_make ("fakesink", NULL)) == NULL);
428 fail_if ((queue = gst_element_factory_make ("queue", NULL)) == NULL);
430 gst_bin_add_many (pipeline, fakesrc, queue, fakesink, NULL);
431 fail_unless (gst_element_link_many (fakesrc, queue, fakesink, NULL));
433 g_object_set (G_OBJECT (fakesink), "sync", FALSE, NULL);
435 /* Send 100 buffers per sec */
436 g_object_set (G_OBJECT (fakesrc), "silent", TRUE, "datarate", 100,
437 "sizemax", 1, "sizetype", 2, NULL);
438 g_object_set (G_OBJECT (queue), "max-size-buffers", 0, "max-size-time",
439 (guint64) GST_SECOND, "max-size-bytes", 0, NULL);
440 g_object_set (G_OBJECT (fakesink), "silent", TRUE, "sync", TRUE, NULL);
442 /* add pad-probes to faksrc.src and fakesink.sink */
443 fail_if ((srcpad = gst_element_get_static_pad (fakesrc, "src")) == NULL);
444 gst_pad_add_event_probe (srcpad, (GCallback) event_probe,
445 GINT_TO_POINTER (TRUE));
447 fail_if ((sinkpad = gst_element_get_static_pad (fakesink, "sink")) == NULL);
448 gst_pad_add_event_probe (sinkpad, (GCallback) event_probe,
449 GINT_TO_POINTER (FALSE));
451 /* Upstream events */
452 test_event (pipeline, GST_EVENT_CUSTOM_UPSTREAM, sinkpad, TRUE, srcpad);
453 fail_unless (timediff (&got_event_time,
454 &sent_event_time) < G_USEC_PER_SEC / 2,
455 "GST_EVENT_CUSTOM_UP took too long to reach source: %"
456 G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time));
458 test_event (pipeline, GST_EVENT_CUSTOM_BOTH, sinkpad, TRUE, srcpad);
459 fail_unless (timediff (&got_event_time,
460 &sent_event_time) < G_USEC_PER_SEC / 2,
461 "GST_EVENT_CUSTOM_BOTH took too long to reach source: %"
462 G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time));
464 test_event (pipeline, GST_EVENT_CUSTOM_BOTH_OOB, sinkpad, TRUE, srcpad);
465 fail_unless (timediff (&got_event_time,
466 &sent_event_time) < G_USEC_PER_SEC / 2,
467 "GST_EVENT_CUSTOM_BOTH_OOB took too long to reach source: %"
468 G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time));
470 /* Out of band downstream events */
471 test_event (pipeline, GST_EVENT_CUSTOM_DOWNSTREAM_OOB, srcpad, FALSE, srcpad);
472 fail_unless (timediff (&got_event_time,
473 &sent_event_time) < G_USEC_PER_SEC / 2,
474 "GST_EVENT_CUSTOM_DS_OOB took too long to reach source: %"
475 G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time));
477 test_event (pipeline, GST_EVENT_CUSTOM_BOTH_OOB, srcpad, FALSE, srcpad);
478 fail_unless (timediff (&got_event_time,
479 &sent_event_time) < G_USEC_PER_SEC / 2,
480 "GST_EVENT_CUSTOM_BOTH_OOB took too long to reach source: %"
481 G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time));
483 /* In-band downstream events are expected to take at least 1 second
484 * to traverse the the queue */
485 test_event (pipeline, GST_EVENT_CUSTOM_DOWNSTREAM, srcpad, FALSE, srcpad);
486 fail_unless (timediff (&got_event_time,
487 &sent_event_time) >= G_USEC_PER_SEC / 2,
488 "GST_EVENT_CUSTOM_DS arrived too quickly for an in-band event: %"
489 G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time));
491 test_event (pipeline, GST_EVENT_CUSTOM_BOTH, srcpad, FALSE, srcpad);
492 fail_unless (timediff (&got_event_time,
493 &sent_event_time) >= G_USEC_PER_SEC / 2,
494 "GST_EVENT_CUSTOM_BOTH arrived too quickly for an in-band event: %"
495 G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time));
497 gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
498 gst_element_get_state (GST_ELEMENT (pipeline), NULL, NULL,
499 GST_CLOCK_TIME_NONE);
501 gst_object_unref (pipeline);
507 gst_event_suite (void)
509 Suite *s = suite_create ("GstEvent");
510 TCase *tc_chain = tcase_create ("events");
512 tcase_set_timeout (tc_chain, 20);
514 suite_add_tcase (s, tc_chain);
515 tcase_add_test (tc_chain, create_events);
516 tcase_add_test (tc_chain, send_custom_events);
520 GST_CHECK_MAIN (gst_event);