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_custom_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, GST_FORMAT_TIME, 1, G_MAXINT64,
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, &format, &start, &end,
78 fail_unless (update == FALSE);
79 fail_unless (rate == 0.5);
80 fail_unless (format == GST_FORMAT_TIME);
81 fail_unless (start == 1);
82 fail_unless (end == G_MAXINT64);
83 fail_unless (base == 0xdeadbeef);
85 /* Check that the new segment was created with applied_rate of 1.0 */
86 gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
87 &format, &start, &end, &base);
89 fail_unless (update == FALSE);
90 fail_unless (rate == 0.5);
91 fail_unless (applied_rate == 1.0);
92 fail_unless (format == GST_FORMAT_TIME);
93 fail_unless (start == 1);
94 fail_unless (end == G_MAXINT64);
96 gst_event_unref (event);
99 gst_event_new_new_segment_full (TRUE, 0.75, 0.5, GST_FORMAT_BYTES, 0,
100 G_MAXINT64 - 1, 0xdeadbeef);
102 fail_if (event == NULL);
103 fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT);
104 fail_if (GST_EVENT_IS_UPSTREAM (event));
105 fail_unless (GST_EVENT_IS_DOWNSTREAM (event));
106 fail_unless (GST_EVENT_IS_SERIALIZED (event));
108 gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
109 &format, &start, &end, &base);
111 fail_unless (update == TRUE);
112 fail_unless (rate == 0.75);
113 fail_unless (applied_rate == 0.5);
114 fail_unless (format == GST_FORMAT_BYTES);
115 fail_unless (start == 0);
116 fail_unless (end == (G_MAXINT64 - 1));
118 gst_event_unref (event);
123 GstTagList *taglist = gst_tag_list_new ();
124 GstTagList *tl2 = NULL;
126 event = gst_event_new_tag (taglist);
127 fail_if (taglist == NULL);
128 fail_if (event == NULL);
129 fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_TAG);
130 fail_if (GST_EVENT_IS_UPSTREAM (event));
131 fail_unless (GST_EVENT_IS_DOWNSTREAM (event));
132 fail_unless (GST_EVENT_IS_SERIALIZED (event));
134 gst_event_parse_tag (event, &tl2);
135 fail_unless (taglist == tl2);
136 gst_event_unref (event);
139 /* FIXME: Add tests for QOS when it is implemented. */
146 GstSeekType cur_type, stop_type;
149 event = gst_event_new_seek (0.5, GST_FORMAT_BYTES,
150 GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE,
151 GST_SEEK_TYPE_SET, 1, GST_SEEK_TYPE_NONE, 0xdeadbeef);
153 fail_if (event == NULL);
154 fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_SEEK);
155 fail_unless (GST_EVENT_IS_UPSTREAM (event));
156 fail_if (GST_EVENT_IS_DOWNSTREAM (event));
157 fail_if (GST_EVENT_IS_SERIALIZED (event));
159 gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
161 fail_unless (rate == 0.5);
162 fail_unless (format == GST_FORMAT_BYTES);
163 fail_unless (flags == (GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE));
164 fail_unless (cur_type == GST_SEEK_TYPE_SET);
165 fail_unless (cur == 1);
166 fail_unless (stop_type == GST_SEEK_TYPE_NONE);
167 fail_unless (stop == 0xdeadbeef);
169 gst_event_unref (event);
174 structure = gst_structure_new ("application/x-gst-navigation", "event",
175 G_TYPE_STRING, "key-press", "key", G_TYPE_STRING, "mon", NULL);
176 fail_if (structure == NULL);
177 event = gst_event_new_navigation (structure);
178 fail_if (event == NULL);
179 fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_NAVIGATION);
180 fail_unless (GST_EVENT_IS_UPSTREAM (event));
181 fail_if (GST_EVENT_IS_DOWNSTREAM (event));
182 fail_if (GST_EVENT_IS_SERIALIZED (event));
184 fail_unless (gst_event_get_structure (event) == structure);
185 gst_event_unref (event);
188 /* Custom event types */
190 structure = gst_structure_empty_new ("application/x-custom");
191 fail_if (structure == NULL);
192 event = gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, structure);
193 fail_if (event == NULL);
194 fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_UPSTREAM);
195 fail_unless (GST_EVENT_IS_UPSTREAM (event));
196 fail_if (GST_EVENT_IS_DOWNSTREAM (event));
197 fail_if (GST_EVENT_IS_SERIALIZED (event));
198 fail_unless (gst_event_get_structure (event) == structure);
199 gst_event_unref (event);
201 /* Decided not to test the other custom enum types, as they
202 * only differ by the value of the enum passed to gst_event_new_custom
208 structure = gst_structure_empty_new ("application/x-custom");
209 fail_if (structure == NULL);
210 event = gst_event_new_custom (GST_EVENT_CUSTOM_BOTH, structure);
212 fail_if (event == NULL);
213 event2 = gst_event_copy (event);
214 fail_if (event2 == NULL);
215 fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_TYPE (event2));
217 /* The structure should have been duplicated */
218 fail_if (gst_event_get_structure (event) ==
219 gst_event_get_structure (event2));
220 gst_event_unref (event);
221 gst_event_unref (event2);
227 GTimeVal sent_event_time;
228 GstEvent *got_event_before_q, *got_event_after_q;
229 GTimeVal got_event_time;
232 event_probe (GstPad * pad, GstMiniObject ** data, gpointer user_data)
234 gboolean before_q = (gboolean) GPOINTER_TO_INT (user_data);
236 fail_unless (GST_IS_EVENT (data));
239 switch (GST_EVENT_TYPE (GST_EVENT (data))) {
240 case GST_EVENT_CUSTOM_UPSTREAM:
241 case GST_EVENT_CUSTOM_BOTH:
242 case GST_EVENT_CUSTOM_BOTH_OOB:
243 if (got_event_before_q != NULL)
245 gst_event_ref ((GstEvent *) data);
246 g_get_current_time (&got_event_time);
247 got_event_before_q = GST_EVENT (data);
253 switch (GST_EVENT_TYPE (GST_EVENT (data))) {
254 case GST_EVENT_CUSTOM_DOWNSTREAM:
255 case GST_EVENT_CUSTOM_DOWNSTREAM_OOB:
256 case GST_EVENT_CUSTOM_BOTH:
257 case GST_EVENT_CUSTOM_BOTH_OOB:
258 if (got_event_after_q != NULL)
260 gst_event_ref ((GstEvent *) data);
261 g_get_current_time (&got_event_time);
262 got_event_after_q = GST_EVENT (data);
272 static void test_event
273 (GstBin * pipeline, GstEventType type, GstPad * pad,
274 gboolean expect_before_q, GstPad * fake_srcpad)
279 got_event_before_q = got_event_after_q = NULL;
281 gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
282 gst_element_get_state (GST_ELEMENT (pipeline), NULL, NULL,
283 GST_CLOCK_TIME_NONE);
285 event = gst_event_new_custom (type,
286 gst_structure_empty_new ("application/x-custom"));
287 g_get_current_time (&sent_event_time);
288 got_event_time.tv_sec = 0;
289 got_event_time.tv_usec = 0;
291 fail_unless (gst_pad_set_blocked (fake_srcpad, TRUE) == TRUE);
292 gst_pad_push_event (pad, event);
293 fail_unless (gst_pad_set_blocked (fake_srcpad, FALSE) == TRUE);
295 /* Wait up to 5 seconds for the event to appear */
296 if (expect_before_q) {
297 for (i = 0; i < 500; i++) {
298 g_usleep (G_USEC_PER_SEC / 100);
299 if (got_event_before_q != NULL)
302 fail_if (got_event_before_q == NULL);
303 fail_unless (GST_EVENT_TYPE (got_event_before_q) == type);
305 for (i = 0; i < 500; i++) {
306 g_usleep (G_USEC_PER_SEC / 100);
307 if (got_event_after_q != NULL)
310 fail_if (got_event_after_q == NULL);
311 fail_unless (GST_EVENT_TYPE (got_event_after_q) == type);
314 gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PAUSED);
315 gst_element_get_state (GST_ELEMENT (pipeline), NULL, NULL,
316 GST_CLOCK_TIME_NONE);
318 if (got_event_before_q)
319 gst_event_unref (got_event_before_q);
320 if (got_event_after_q)
321 gst_event_unref (got_event_after_q);
323 got_event_before_q = got_event_after_q = NULL;
327 timediff (GTimeVal * end, GTimeVal * start)
329 return (end->tv_sec - start->tv_sec) * G_USEC_PER_SEC +
330 (end->tv_usec - start->tv_usec);
333 GST_START_TEST (send_custom_events)
335 /* Run some tests on custom events. Checking for serialisation and whatnot.
336 * pipeline is fakesrc ! queue ! fakesink */
338 GstElement *fakesrc, *fakesink, *queue;
339 GstPad *srcpad, *sinkpad;
341 fail_if ((pipeline = (GstBin *) gst_pipeline_new ("testpipe")) == NULL);
342 fail_if ((fakesrc = gst_element_factory_make ("fakesrc", NULL)) == NULL);
343 fail_if ((fakesink = gst_element_factory_make ("fakesink", NULL)) == NULL);
344 fail_if ((queue = gst_element_factory_make ("queue", NULL)) == NULL);
346 gst_bin_add_many (pipeline, fakesrc, queue, fakesink, NULL);
347 fail_unless (gst_element_link_many (fakesrc, queue, fakesink, NULL));
349 g_object_set (G_OBJECT (fakesink), "sync", FALSE, NULL);
351 /* Send 100 buffers per sec */
352 g_object_set (G_OBJECT (fakesrc), "silent", TRUE, "datarate", 100,
353 "sizemax", 1, "sizetype", 2, NULL);
354 g_object_set (G_OBJECT (queue), "max-size-buffers", 0, "max-size-time",
355 (guint64) GST_SECOND, "max-size-bytes", 0, NULL);
356 g_object_set (G_OBJECT (fakesink), "silent", TRUE, "sync", TRUE, NULL);
358 fail_if ((srcpad = gst_element_get_pad (fakesrc, "src")) == NULL);
359 gst_pad_add_event_probe (srcpad, (GCallback) event_probe,
360 GINT_TO_POINTER (TRUE));
362 fail_if ((sinkpad = gst_element_get_pad (fakesink, "sink")) == NULL);
363 gst_pad_add_event_probe (sinkpad, (GCallback) event_probe,
364 GINT_TO_POINTER (FALSE));
366 /* Upstream events */
367 test_event (pipeline, GST_EVENT_CUSTOM_UPSTREAM, sinkpad, TRUE, srcpad);
368 fail_unless (timediff (&got_event_time,
369 &sent_event_time) < G_USEC_PER_SEC / 2,
370 "GST_EVENT_CUSTOM_UP took to long to reach source: %"
371 G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time));
373 test_event (pipeline, GST_EVENT_CUSTOM_BOTH, sinkpad, TRUE, srcpad);
374 fail_unless (timediff (&got_event_time,
375 &sent_event_time) < G_USEC_PER_SEC / 2,
376 "GST_EVENT_CUSTOM_BOTH took to long to reach source: %"
377 G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time));
379 test_event (pipeline, GST_EVENT_CUSTOM_BOTH_OOB, sinkpad, TRUE, srcpad);
380 fail_unless (timediff (&got_event_time,
381 &sent_event_time) < G_USEC_PER_SEC / 2,
382 "GST_EVENT_CUSTOM_BOTH_OOB took to long to reach source: %"
383 G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time));
385 /* Out of band downstream events */
386 test_event (pipeline, GST_EVENT_CUSTOM_DOWNSTREAM_OOB, srcpad, FALSE, srcpad);
387 fail_unless (timediff (&got_event_time,
388 &sent_event_time) < G_USEC_PER_SEC / 2,
389 "GST_EVENT_CUSTOM_DS_OOB took to long to reach source: %"
390 G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time));
392 test_event (pipeline, GST_EVENT_CUSTOM_BOTH_OOB, srcpad, FALSE, srcpad);
393 fail_unless (timediff (&got_event_time,
394 &sent_event_time) < G_USEC_PER_SEC / 2,
395 "GST_EVENT_CUSTOM_BOTH_OOB took to long to reach source: %"
396 G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time));
398 /* In-band downstream events are expected to take at least 1 second
399 * to traverse the the queue */
400 test_event (pipeline, GST_EVENT_CUSTOM_DOWNSTREAM, srcpad, FALSE, srcpad);
401 fail_unless (timediff (&got_event_time,
402 &sent_event_time) >= G_USEC_PER_SEC / 2,
403 "GST_EVENT_CUSTOM_DS arrived too quickly for an in-band event: %"
404 G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time));
406 test_event (pipeline, GST_EVENT_CUSTOM_BOTH, srcpad, FALSE, srcpad);
407 fail_unless (timediff (&got_event_time,
408 &sent_event_time) >= G_USEC_PER_SEC / 2,
409 "GST_EVENT_CUSTOM_BOTH arrived too quickly for an in-band event: %"
410 G_GINT64_FORMAT " us", timediff (&got_event_time, &sent_event_time));
412 gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
413 gst_element_get_state (GST_ELEMENT (pipeline), NULL, NULL,
414 GST_CLOCK_TIME_NONE);
416 gst_object_unref (pipeline);
422 gst_event_suite (void)
424 Suite *s = suite_create ("GstEvent");
425 TCase *tc_chain = tcase_create ("customevents");
427 tcase_set_timeout (tc_chain, 20);
429 suite_add_tcase (s, tc_chain);
430 tcase_add_test (tc_chain, create_custom_events);
431 tcase_add_test (tc_chain, send_custom_events);
435 GST_CHECK_MAIN (gst_event);