tests/check/: use the new macro
[platform/upstream/gstreamer.git] / tests / check / gst / gstevent.c
1 /* GStreamer
2  * Copyright (C) 2005 Jan Schmidt <thaytan@mad.scientist.com>
3  *
4  * gstevent.c: Unit test for event handling
5  *
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.
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  * Library General Public License for more details.
15  *
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.
20  */
21
22
23 #include <gst/check/gstcheck.h>
24
25 GST_START_TEST (create_custom_events)
26 {
27   GstEvent *event, *event2;
28   GstStructure *structure;
29
30   /* FLUSH_START */
31   {
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);
39   }
40   /* FLUSH_STOP */
41   {
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);
49   }
50   /* EOS */
51   {
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);
59   }
60   /* NEWSEGMENT */
61   {
62     gdouble rate, applied_rate;
63     GstFormat format;
64     gint64 start, end, base;
65     gboolean update;
66
67     event =
68         gst_event_new_new_segment (FALSE, 0.5, GST_FORMAT_TIME, 1, G_MAXINT64,
69         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));
75
76     gst_event_parse_new_segment (event, &update, &rate, &format, &start, &end,
77         &base);
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);
84
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);
88
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);
95
96     gst_event_unref (event);
97
98     event =
99         gst_event_new_new_segment_full (TRUE, 0.75, 0.5, GST_FORMAT_BYTES, 0,
100         G_MAXINT64 - 1, 0xdeadbeef);
101
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));
107
108     gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
109         &format, &start, &end, &base);
110
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));
117
118     gst_event_unref (event);
119   }
120
121   /* TAGS */
122   {
123     GstTagList *taglist = gst_tag_list_new ();
124     GstTagList *tl2 = NULL;
125
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));
133
134     gst_event_parse_tag (event, &tl2);
135     fail_unless (taglist == tl2);
136     gst_event_unref (event);
137   }
138
139   /* FIXME: Add tests for QOS when it is implemented. */
140
141   /* SEEK */
142   {
143     gdouble rate;
144     GstFormat format;
145     GstSeekFlags flags;
146     GstSeekType cur_type, stop_type;
147     gint64 cur, stop;
148
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);
152
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));
158
159     gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
160         &stop_type, &stop);
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);
168
169     gst_event_unref (event);
170   }
171
172   /* NAVIGATION */
173   {
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));
183
184     fail_unless (gst_event_get_structure (event) == structure);
185     gst_event_unref (event);
186   }
187
188   /* Custom event types */
189   {
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);
200
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
203      */
204   }
205
206   /* Event copying */
207   {
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);
211
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));
216
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);
222   }
223 }
224
225 GST_END_TEST;
226
227 GTimeVal sent_event_time;
228 GstEvent *got_event_before_q, *got_event_after_q;
229 GTimeVal got_event_time;
230
231 static gboolean
232 event_probe (GstPad * pad, GstMiniObject ** data, gpointer user_data)
233 {
234   gboolean before_q = (gboolean) GPOINTER_TO_INT (user_data);
235
236   fail_unless (GST_IS_EVENT (data));
237
238   if (before_q) {
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)
244           break;
245         gst_event_ref ((GstEvent *) data);
246         g_get_current_time (&got_event_time);
247         got_event_before_q = GST_EVENT (data);
248         break;
249       default:
250         break;
251     }
252   } else {
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)
259           break;
260         gst_event_ref ((GstEvent *) data);
261         g_get_current_time (&got_event_time);
262         got_event_after_q = GST_EVENT (data);
263         break;
264       default:
265         break;
266     }
267   }
268
269   return TRUE;
270 }
271
272 static void test_event
273     (GstBin * pipeline, GstEventType type, GstPad * pad,
274     gboolean expect_before_q, GstPad * fake_srcpad)
275 {
276   GstEvent *event;
277   gint i;
278
279   got_event_before_q = got_event_after_q = NULL;
280
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);
284
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;
290
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);
294
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)
300         break;
301     }
302     fail_if (got_event_before_q == NULL);
303     fail_unless (GST_EVENT_TYPE (got_event_before_q) == type);
304   } else {
305     for (i = 0; i < 500; i++) {
306       g_usleep (G_USEC_PER_SEC / 100);
307       if (got_event_after_q != NULL)
308         break;
309     }
310     fail_if (got_event_after_q == NULL);
311     fail_unless (GST_EVENT_TYPE (got_event_after_q) == type);
312   }
313
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);
317
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);
322
323   got_event_before_q = got_event_after_q = NULL;
324 }
325
326 static gint64
327 timediff (GTimeVal * end, GTimeVal * start)
328 {
329   return (end->tv_sec - start->tv_sec) * G_USEC_PER_SEC +
330       (end->tv_usec - start->tv_usec);
331 }
332
333 GST_START_TEST (send_custom_events)
334 {
335   /* Run some tests on custom events. Checking for serialisation and whatnot.
336    * pipeline is fakesrc ! queue ! fakesink */
337   GstBin *pipeline;
338   GstElement *fakesrc, *fakesink, *queue;
339   GstPad *srcpad, *sinkpad;
340
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);
345
346   gst_bin_add_many (pipeline, fakesrc, queue, fakesink, NULL);
347   fail_unless (gst_element_link_many (fakesrc, queue, fakesink, NULL));
348
349   g_object_set (G_OBJECT (fakesink), "sync", FALSE, NULL);
350
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);
357
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));
361
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));
365
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));
372
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));
378
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));
384
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));
391
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));
397
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));
405
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));
411
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);
415
416   gst_object_unref (pipeline);
417 }
418
419 GST_END_TEST;
420
421 Suite *
422 gst_event_suite (void)
423 {
424   Suite *s = suite_create ("GstEvent");
425   TCase *tc_chain = tcase_create ("customevents");
426
427   tcase_set_timeout (tc_chain, 20);
428
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);
432   return s;
433 }
434
435 GST_CHECK_MAIN (gst_event);