And correct even more valid sparse warnings.
[platform/upstream/gstreamer.git] / tests / check / gst / gstbin.c
1 /* GStreamer
2  * Copyright (C) 2005 Wim Taymans <wim@fluendo.com>
3  * Copyright (C) 2005 Thomas Vander Stichele <thomas at apestaart dot org>
4  *
5  * gstbin.c: Unit test for GstBin
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #include <gst/check/gstcheck.h>
24
25 static void
26 pop_async_done (GstBus * bus)
27 {
28   GstMessage *message;
29
30   GST_DEBUG ("popping async-done message");
31   message = gst_bus_poll (bus, GST_MESSAGE_ASYNC_DONE, -1);
32
33   fail_unless (message && GST_MESSAGE_TYPE (message)
34       == GST_MESSAGE_ASYNC_DONE, "did not get GST_MESSAGE_ASYNC_DONE");
35
36   gst_message_unref (message);
37   GST_DEBUG ("popped message");
38 }
39
40 static void
41 pop_messages (GstBus * bus, int count)
42 {
43   GstMessage *message;
44
45   int i;
46
47   GST_DEBUG ("popping %d messages", count);
48   for (i = 0; i < count; ++i) {
49     message = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, -1);
50
51     fail_unless (message && GST_MESSAGE_TYPE (message)
52         == GST_MESSAGE_STATE_CHANGED, "did not get GST_MESSAGE_STATE_CHANGED");
53
54     gst_message_unref (message);
55   }
56   GST_DEBUG ("popped %d messages", count);
57 }
58
59 GST_START_TEST (test_interface)
60 {
61   GstBin *bin, *bin2;
62   GstElement *filesrc;
63   GstIterator *it;
64   gpointer item;
65
66   bin = GST_BIN (gst_bin_new (NULL));
67   fail_unless (bin != NULL, "Could not create bin");
68
69   filesrc = gst_element_factory_make ("filesrc", NULL);
70   fail_unless (filesrc != NULL, "Could not create filesrc");
71   fail_unless (GST_IS_URI_HANDLER (filesrc), "Filesrc not a URI handler");
72   gst_bin_add (bin, filesrc);
73
74   fail_unless (gst_bin_get_by_interface (bin, GST_TYPE_URI_HANDLER) == filesrc);
75   gst_object_unref (filesrc);
76
77   it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER);
78   fail_unless (it != NULL);
79   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
80   fail_unless (item == (gpointer) filesrc);
81   gst_object_unref (GST_OBJECT (item));
82   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
83   gst_iterator_free (it);
84
85   gst_bin_add_many (bin,
86       gst_element_factory_make ("identity", NULL),
87       gst_element_factory_make ("identity", NULL),
88       gst_element_factory_make ("identity", NULL), NULL);
89   it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER);
90   fail_unless (it != NULL);
91   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
92   fail_unless (item == (gpointer) filesrc);
93   gst_object_unref (GST_OBJECT (item));
94   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
95   gst_iterator_free (it);
96
97   bin2 = bin;
98   bin = GST_BIN (gst_bin_new (NULL));
99   fail_unless (bin != NULL);
100   gst_bin_add_many (bin,
101       gst_element_factory_make ("identity", NULL),
102       gst_element_factory_make ("identity", NULL),
103       GST_ELEMENT (bin2), gst_element_factory_make ("identity", NULL), NULL);
104   it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER);
105   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
106   fail_unless (item == (gpointer) filesrc);
107   gst_object_unref (GST_OBJECT (item));
108   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
109   gst_iterator_free (it);
110
111   gst_bin_add (bin, gst_element_factory_make ("filesrc", NULL));
112   gst_bin_add (bin2, gst_element_factory_make ("filesrc", NULL));
113   it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER);
114   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
115   gst_object_unref (GST_OBJECT (item));
116   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
117   gst_object_unref (GST_OBJECT (item));
118   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
119   gst_object_unref (GST_OBJECT (item));
120   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
121   gst_iterator_free (it);
122
123   gst_object_unref (bin);
124 }
125
126 GST_END_TEST;
127
128 GST_START_TEST (test_message_state_changed)
129 {
130   GstBin *bin;
131   GstBus *bus;
132   GstMessage *message;
133   GstStateChangeReturn ret;
134
135   bin = GST_BIN (gst_bin_new (NULL));
136   fail_unless (bin != NULL, "Could not create bin");
137   ASSERT_OBJECT_REFCOUNT (bin, "bin", 1);
138
139   bus = g_object_new (gst_bus_get_type (), NULL);
140   gst_element_set_bus (GST_ELEMENT_CAST (bin), bus);
141
142   /* change state, spawning a message, causing an incref on the bin */
143   ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_READY);
144   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
145
146   ASSERT_OBJECT_REFCOUNT (bin, "bin", 2);
147
148   /* get and unref the message, causing a decref on the bin */
149   message = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, -1);
150
151   fail_unless (message && GST_MESSAGE_TYPE (message)
152       == GST_MESSAGE_STATE_CHANGED, "did not get GST_MESSAGE_STATE_CHANGED");
153
154   gst_message_unref (message);
155
156   ASSERT_OBJECT_REFCOUNT (bin, "bin", 1);
157
158   /* clean up */
159   ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL);
160   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
161
162   gst_object_unref (bus);
163   gst_object_unref (bin);
164 }
165
166 GST_END_TEST;
167
168 GST_START_TEST (test_message_state_changed_child)
169 {
170   GstBin *bin;
171   GstElement *src;
172   GstBus *bus;
173   GstMessage *message;
174   GstStateChangeReturn ret;
175
176   bin = GST_BIN (gst_bin_new (NULL));
177   fail_unless (bin != NULL, "Could not create bin");
178   ASSERT_OBJECT_REFCOUNT (bin, "bin", 1);
179
180   bus = g_object_new (gst_bus_get_type (), NULL);
181   gst_element_set_bus (GST_ELEMENT_CAST (bin), bus);
182
183   src = gst_element_factory_make ("fakesrc", NULL);
184   fail_if (src == NULL, "Could not create fakesrc");
185   gst_bin_add (bin, src);
186   ASSERT_OBJECT_REFCOUNT (bin, "bin", 1);
187   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
188
189   /* change state, spawning two messages:
190    * - first for fakesrc, forwarded to bin's bus, causing incref on fakesrc
191    * - second for bin, causing an incref on the bin */
192   GST_DEBUG ("setting bin to READY");
193   ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_READY);
194   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
195
196   ASSERT_OBJECT_REFCOUNT (src, "src", 2);
197   ASSERT_OBJECT_REFCOUNT (bin, "bin", 2);
198
199   /* get and unref the message, causing a decref on the src */
200   message = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, -1);
201   fail_unless (message && GST_MESSAGE_TYPE (message)
202       == GST_MESSAGE_STATE_CHANGED, "did not get GST_MESSAGE_STATE_CHANGED");
203
204   fail_unless (message->src == GST_OBJECT (src));
205   gst_message_unref (message);
206
207   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
208   ASSERT_OBJECT_REFCOUNT (bin, "bin", 2);
209
210   /* get and unref message 2, causing a decref on the bin */
211   message = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, -1);
212   fail_unless (message && GST_MESSAGE_TYPE (message)
213       == GST_MESSAGE_STATE_CHANGED, "did not get GST_MESSAGE_STATE_CHANGED");
214
215   fail_unless (message->src == GST_OBJECT (bin));
216   gst_message_unref (message);
217
218   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
219   ASSERT_OBJECT_REFCOUNT (bin, "bin", 1);
220
221   /* clean up */
222   ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL);
223   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
224   gst_object_unref (bus);
225   gst_object_unref (bin);
226 }
227
228 GST_END_TEST;
229
230 GST_START_TEST (test_message_state_changed_children)
231 {
232   GstPipeline *pipeline;
233   GstElement *src, *sink;
234   GstBus *bus;
235   GstStateChangeReturn ret;
236   GstState current, pending;
237
238   pipeline = GST_PIPELINE (gst_pipeline_new (NULL));
239   fail_unless (pipeline != NULL, "Could not create pipeline");
240   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
241
242   src = gst_element_factory_make ("fakesrc", NULL);
243   fail_if (src == NULL, "Could not create fakesrc");
244   /* need to silence the element as the deep_notify refcounts the
245    * parents while running */
246   g_object_set (G_OBJECT (src), "silent", TRUE, NULL);
247   gst_bin_add (GST_BIN (pipeline), src);
248
249   sink = gst_element_factory_make ("fakesink", NULL);
250   /* need to silence the element as the deep_notify refcounts the
251    * parents while running */
252   g_object_set (G_OBJECT (sink), "silent", TRUE, NULL);
253   fail_if (sink == NULL, "Could not create fakesink");
254   gst_bin_add (GST_BIN (pipeline), sink);
255
256   fail_unless (gst_element_link (src, sink), "could not link src and sink");
257
258   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
259   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
260   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
261
262   bus = gst_pipeline_get_bus (pipeline);
263
264   /* change state to READY, spawning three messages */
265   GST_DEBUG ("setting pipeline to READY");
266   ret = gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_READY);
267   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
268
269   /* each object is referenced by a message */
270   ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
271   ASSERT_OBJECT_REFCOUNT (src, "src", 2);
272   ASSERT_OBJECT_REFCOUNT (sink, "sink", 2);
273   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 2);
274
275   pop_messages (bus, 3);
276   fail_if (gst_bus_have_pending (bus), "unexpected pending messages");
277
278   ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
279   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
280   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
281   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
282
283   /* change state to PAUSED, spawning three messages */
284   GST_DEBUG ("setting pipeline to PAUSED");
285   ret = gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PAUSED);
286   fail_unless (ret == GST_STATE_CHANGE_ASYNC);
287   ret =
288       gst_element_get_state (GST_ELEMENT (pipeline), &current, &pending,
289       GST_CLOCK_TIME_NONE);
290   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
291   fail_unless (current == GST_STATE_PAUSED);
292   fail_unless (pending == GST_STATE_VOID_PENDING);
293
294   /* wait for async thread to settle down */
295   while (GST_OBJECT_REFCOUNT_VALUE (pipeline) > 3)
296     THREAD_SWITCH ();
297
298   /* each object is referenced by a message;
299    * base_src is blocked in the push and has an extra refcount.
300    * base_sink_chain has taken a refcount on the sink, and is blocked on
301    * preroll */
302   ASSERT_OBJECT_REFCOUNT (src, "src", 2);
303   /* refcount can be 4 if the bin is still processing the async_done message of
304    * the sink. */
305   ASSERT_OBJECT_REFCOUNT_BETWEEN (sink, "sink", 2, 3);
306   /* 2 or 3 is valid, because the pipeline might still be posting 
307    * its state_change message */
308   ASSERT_OBJECT_REFCOUNT_BETWEEN (pipeline, "pipeline", 2, 3);
309
310   pop_messages (bus, 3);
311   pop_async_done (bus);
312   fail_if ((gst_bus_pop (bus)) != NULL);
313
314   ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
315   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
316   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
317   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
318
319   /* change state to PLAYING, spawning three messages */
320   GST_DEBUG ("setting pipeline to PLAYING");
321   ret = gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
322   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
323   ret =
324       gst_element_get_state (GST_ELEMENT (pipeline), &current, &pending,
325       GST_CLOCK_TIME_NONE);
326   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
327   fail_unless (current == GST_STATE_PLAYING);
328   fail_unless (pending == GST_STATE_VOID_PENDING);
329
330   /* each object is referenced by one message
331    * src might have an extra reference if it's still pushing
332    * sink might have an extra reference if it's still blocked on preroll
333    * pipeline posted a new-clock message too. */
334   ASSERT_OBJECT_REFCOUNT_BETWEEN (src, "src", 2, 3);
335   ASSERT_OBJECT_REFCOUNT_BETWEEN (sink, "sink", 2, 3);
336   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 3);
337
338   pop_messages (bus, 3);
339   fail_if ((gst_bus_pop (bus)) != NULL);
340
341   ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
342   /* src might have an extra reference if it's still pushing */
343   ASSERT_OBJECT_REFCOUNT_BETWEEN (src, "src", 1, 2);
344   /* sink might have an extra reference if it's still blocked on preroll */
345   ASSERT_OBJECT_REFCOUNT_BETWEEN (sink, "sink", 1, 2);
346   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
347
348   /* go back to READY, spawning six messages */
349   GST_DEBUG ("setting pipeline to READY");
350   ret = gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_READY);
351   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
352
353   /* each object is referenced by two messages */
354   ASSERT_OBJECT_REFCOUNT (src, "src", 3);
355   ASSERT_OBJECT_REFCOUNT (sink, "sink", 3);
356   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 3);
357
358   pop_messages (bus, 6);
359   fail_if ((gst_bus_pop (bus)) != NULL);
360
361   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
362   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
363   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
364
365   /* setting pipeline to NULL flushes the bus automatically */
366   ret = gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
367   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
368
369   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
370   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
371   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
372
373   /* clean up */
374   gst_object_unref (bus);
375   gst_object_unref (pipeline);
376 }
377
378 GST_END_TEST;
379
380 GST_START_TEST (test_watch_for_state_change)
381 {
382   GstElement *src, *sink, *bin;
383   GstBus *bus;
384   GstStateChangeReturn ret;
385
386   bin = gst_element_factory_make ("bin", NULL);
387   fail_unless (bin != NULL, "Could not create bin");
388
389   bus = g_object_new (gst_bus_get_type (), NULL);
390   gst_element_set_bus (GST_ELEMENT_CAST (bin), bus);
391
392   src = gst_element_factory_make ("fakesrc", NULL);
393   fail_if (src == NULL, "Could not create fakesrc");
394   sink = gst_element_factory_make ("fakesink", NULL);
395   fail_if (sink == NULL, "Could not create fakesink");
396
397   gst_bin_add (GST_BIN (bin), sink);
398   gst_bin_add (GST_BIN (bin), src);
399
400   fail_unless (gst_element_link (src, sink), "could not link src and sink");
401
402   /* change state, spawning two times three messages */
403   ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED);
404   fail_unless (ret == GST_STATE_CHANGE_ASYNC);
405   ret =
406       gst_element_get_state (GST_ELEMENT (bin), NULL, NULL,
407       GST_CLOCK_TIME_NONE);
408   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
409
410   pop_messages (bus, 6);
411   pop_async_done (bus);
412
413   fail_unless (gst_bus_have_pending (bus) == FALSE,
414       "Unexpected messages on bus");
415
416   ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PLAYING);
417   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
418
419   pop_messages (bus, 3);
420
421   /* this one might return either SUCCESS or ASYNC, likely SUCCESS */
422   ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED);
423   gst_element_get_state (GST_ELEMENT (bin), NULL, NULL, GST_CLOCK_TIME_NONE);
424
425   pop_messages (bus, 3);
426   if (ret == GST_STATE_CHANGE_ASYNC)
427     pop_async_done (bus);
428
429   fail_unless (gst_bus_have_pending (bus) == FALSE,
430       "Unexpected messages on bus");
431
432   /* setting bin to NULL flushes the bus automatically */
433   ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL);
434   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
435
436   /* clean up */
437   gst_object_unref (bus);
438   gst_object_unref (bin);
439 }
440
441 GST_END_TEST;
442
443 /* adding an element with linked pads to a bin unlinks the
444  * pads */
445 GST_START_TEST (test_add_linked)
446 {
447   GstElement *src, *sink;
448   GstPad *srcpad, *sinkpad;
449   GstElement *pipeline;
450
451   pipeline = gst_pipeline_new (NULL);
452   fail_unless (pipeline != NULL, "Could not create pipeline");
453
454   src = gst_element_factory_make ("fakesrc", NULL);
455   fail_if (src == NULL, "Could not create fakesrc");
456   sink = gst_element_factory_make ("fakesink", NULL);
457   fail_if (sink == NULL, "Could not create fakesink");
458
459   srcpad = gst_element_get_pad (src, "src");
460   fail_unless (srcpad != NULL);
461   sinkpad = gst_element_get_pad (sink, "sink");
462   fail_unless (sinkpad != NULL);
463
464   fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK);
465
466   /* pads are linked now */
467   fail_unless (gst_pad_is_linked (srcpad));
468   fail_unless (gst_pad_is_linked (sinkpad));
469
470   /* adding element to bin voids hierarchy so pads are unlinked */
471   gst_bin_add (GST_BIN (pipeline), src);
472
473   /* check if pads really are unlinked */
474   fail_unless (!gst_pad_is_linked (srcpad));
475   fail_unless (!gst_pad_is_linked (sinkpad));
476
477   /* cannot link pads in wrong hierarchy */
478   fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_WRONG_HIERARCHY);
479
480   /* adding other element to bin as well */
481   gst_bin_add (GST_BIN (pipeline), sink);
482
483   /* now we can link again */
484   fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK);
485
486   /* check if pads really are linked */
487   fail_unless (gst_pad_is_linked (srcpad));
488   fail_unless (gst_pad_is_linked (sinkpad));
489
490   gst_object_unref (srcpad);
491   gst_object_unref (sinkpad);
492   gst_object_unref (pipeline);
493 }
494
495 GST_END_TEST;
496
497 /* adding ourself should fail */
498 GST_START_TEST (test_add_self)
499 {
500   GstElement *bin;
501
502   bin = gst_bin_new (NULL);
503   fail_unless (bin != NULL, "Could not create bin");
504
505   ASSERT_WARNING (gst_bin_add (GST_BIN (bin), bin));
506
507   gst_object_unref (bin);
508 }
509
510 GST_END_TEST;
511
512
513 /* g_print ("%10s: %4d => %4d\n", GST_OBJECT_NAME (msg->src), old, new); */
514
515 #define ASSERT_STATE_CHANGE_MSG(bus,element,old_state,new_state,num)          \
516   {                                                                           \
517     GstMessage *msg;                                                          \
518     GstState old = 0, new = 0, pending = 0;                                   \
519     msg = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, GST_SECOND);          \
520     fail_if (msg == NULL, "No state change message within 1 second (#"        \
521         G_STRINGIFY (num) ")");                                               \
522     gst_message_parse_state_changed (msg, &old, &new, &pending);              \
523     fail_if (msg->src != GST_OBJECT (element), G_STRINGIFY(element)           \
524         " should have changed state next (#" G_STRINGIFY (num) ")");          \
525     fail_if (old != old_state || new != new_state, "state change is not "     \
526         G_STRINGIFY (old_state) " => " G_STRINGIFY (new_state));              \
527     gst_message_unref (msg);                                                  \
528   }
529
530 GST_START_TEST (test_children_state_change_order_flagged_sink)
531 {
532   GstElement *src, *identity, *sink, *pipeline;
533   GstStateChangeReturn ret;
534   GstState current, pending;
535   GstBus *bus;
536
537   pipeline = gst_pipeline_new (NULL);
538   fail_unless (pipeline != NULL, "Could not create pipeline");
539
540   bus = gst_element_get_bus (pipeline);
541   fail_unless (bus != NULL, "Pipeline has no bus?!");
542
543   src = gst_element_factory_make ("fakesrc", NULL);
544   fail_if (src == NULL, "Could not create fakesrc");
545   g_object_set (src, "num-buffers", 5, NULL);
546
547   identity = gst_element_factory_make ("identity", NULL);
548   fail_if (identity == NULL, "Could not create identity");
549
550   sink = gst_element_factory_make ("fakesink", NULL);
551   fail_if (sink == NULL, "Could not create fakesink");
552
553   gst_bin_add_many (GST_BIN (pipeline), src, identity, sink, NULL);
554
555   fail_unless (gst_element_link (src, identity) == TRUE);
556   fail_unless (gst_element_link (identity, sink) == TRUE);
557
558   /* (1) Test state change with fakesink being a regular sink */
559   ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
560   fail_if (ret != GST_STATE_CHANGE_ASYNC,
561       "State change to PLAYING did not return ASYNC");
562   ret =
563       gst_element_get_state (pipeline, &current, &pending, GST_CLOCK_TIME_NONE);
564   fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to PLAYING failed");
565   fail_if (current != GST_STATE_PLAYING, "State change to PLAYING failed");
566   fail_if (pending != GST_STATE_VOID_PENDING, "State change to PLAYING failed");
567
568   /* NULL => READY */
569   ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_NULL, GST_STATE_READY, 101);
570   ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_NULL, GST_STATE_READY, 102);
571   ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_NULL, GST_STATE_READY, 103);
572   ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_NULL, GST_STATE_READY, 104);
573
574   /* READY => PAUSED */
575   /* because of pre-rolling, sink will return ASYNC on state
576    * change and change state later when it has a buffer */
577   GST_DEBUG ("popping READY -> PAUSED messages");
578   ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_READY, GST_STATE_PAUSED,
579       105);
580 #if 0
581   /* From here on, all bets are off. Usually the source changes state next,
582    * but it might just as well be that the first buffer produced by the
583    * source reaches the sink before the source has finished its state change,
584    * in which case the sink will commit its new state before the source ...  */
585   ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_READY, GST_STATE_PAUSED, 106);
586   ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_READY, GST_STATE_PAUSED, 107);
587 #else
588
589   pop_messages (bus, 2);        /* pop remaining ready => paused messages off the bus */
590   ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_READY, GST_STATE_PAUSED,
591       108);
592   pop_async_done (bus);
593 #endif
594   /* PAUSED => PLAYING */
595   GST_DEBUG ("popping PAUSED -> PLAYING messages");
596   ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_PAUSED, GST_STATE_PLAYING, 109);
597   ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_PAUSED, GST_STATE_PLAYING,
598       110);
599   ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_PAUSED, GST_STATE_PLAYING, 111);
600   ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_PAUSED, GST_STATE_PLAYING,
601       112);
602
603   /* don't set to NULL that will set the bus flushing and kill our messages */
604   ret = gst_element_set_state (pipeline, GST_STATE_READY);
605   fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to READY failed");
606   ret = gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
607   fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to READY failed");
608
609   /* TODO: do we need to check downwards state change order as well? */
610   pop_messages (bus, 4);        /* pop playing => paused messages off the bus */
611   pop_messages (bus, 4);        /* pop paused => ready messages off the bus */
612
613   while (GST_OBJECT_REFCOUNT_VALUE (pipeline) > 1)
614     THREAD_SWITCH ();
615
616   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
617   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
618   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
619
620   ret = gst_element_set_state (pipeline, GST_STATE_NULL);
621   fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to NULL failed");
622
623   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
624   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
625   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
626
627   gst_object_unref (bus);
628   gst_object_unref (pipeline);
629 }
630
631 GST_END_TEST;
632
633
634 GST_START_TEST (test_children_state_change_order_semi_sink)
635 {
636   GstElement *src, *identity, *sink, *pipeline;
637   GstStateChangeReturn ret;
638   GstState current, pending;
639   GstBus *bus;
640
641   /* (2) Now again, but check other code path where we don't have
642    *     a proper sink correctly flagged as such, but a 'semi-sink' */
643   pipeline = gst_pipeline_new (NULL);
644   fail_unless (pipeline != NULL, "Could not create pipeline");
645
646   bus = gst_element_get_bus (pipeline);
647   fail_unless (bus != NULL, "Pipeline has no bus?!");
648
649   src = gst_element_factory_make ("fakesrc", NULL);
650   fail_if (src == NULL, "Could not create fakesrc");
651
652   identity = gst_element_factory_make ("identity", NULL);
653   fail_if (identity == NULL, "Could not create identity");
654
655   sink = gst_element_factory_make ("fakesink", NULL);
656   fail_if (sink == NULL, "Could not create fakesink");
657
658   gst_bin_add_many (GST_BIN (pipeline), src, identity, sink, NULL);
659
660   fail_unless (gst_element_link (src, identity) == TRUE);
661   fail_unless (gst_element_link (identity, sink) == TRUE);
662
663   /* this is not very nice but should work just fine in this case. */
664   GST_OBJECT_FLAG_UNSET (sink, GST_ELEMENT_IS_SINK);    /* <======== */
665
666   ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
667   fail_if (ret != GST_STATE_CHANGE_ASYNC, "State change to PLAYING not ASYNC");
668   ret =
669       gst_element_get_state (pipeline, &current, &pending, GST_CLOCK_TIME_NONE);
670   fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to PLAYING failed");
671   fail_if (current != GST_STATE_PLAYING, "State change to PLAYING failed");
672   fail_if (pending != GST_STATE_VOID_PENDING, "State change to PLAYING failed");
673
674   /* NULL => READY */
675   ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_NULL, GST_STATE_READY, 201);
676   ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_NULL, GST_STATE_READY, 202);
677   ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_NULL, GST_STATE_READY, 203);
678   ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_NULL, GST_STATE_READY, 204);
679
680   /* READY => PAUSED */
681   /* because of pre-rolling, sink will return ASYNC on state
682    * change and change state later when it has a buffer */
683   GST_DEBUG ("popping READY -> PAUSED messages");
684   ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_READY, GST_STATE_PAUSED,
685       205);
686 #if 0
687   /* From here on, all bets are off. Usually the source changes state next,
688    * but it might just as well be that the first buffer produced by the
689    * source reaches the sink before the source has finished its state change,
690    * in which case the sink will commit its new state before the source ...  */
691   ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_READY, GST_STATE_PAUSED, 206);
692   ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_READY, GST_STATE_PAUSED, 207);
693 #else
694   pop_messages (bus, 2);        /* pop remaining ready => paused messages off the bus */
695   ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_READY, GST_STATE_PAUSED,
696       208);
697   pop_async_done (bus);
698
699   /* PAUSED => PLAYING */
700   GST_DEBUG ("popping PAUSED -> PLAYING messages");
701   ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_PAUSED, GST_STATE_PLAYING, 209);
702   ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_PAUSED, GST_STATE_PLAYING,
703       210);
704   ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_PAUSED, GST_STATE_PLAYING, 211);
705   ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_PAUSED, GST_STATE_PLAYING,
706       212);
707 #endif
708
709   /* don't set to NULL that will set the bus flushing and kill our messages */
710   ret = gst_element_set_state (pipeline, GST_STATE_READY);
711   fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to READY failed");
712
713   /* TODO: do we need to check downwards state change order as well? */
714   pop_messages (bus, 4);        /* pop playing => paused messages off the bus */
715   pop_messages (bus, 4);        /* pop paused => ready messages off the bus */
716
717   GST_DEBUG ("waiting for pipeline to reach refcount 1");
718   while (GST_OBJECT_REFCOUNT_VALUE (pipeline) > 1)
719     THREAD_SWITCH ();
720
721   GST_DEBUG ("checking refcount");
722   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
723   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
724   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
725
726   ret = gst_element_set_state (pipeline, GST_STATE_NULL);
727   fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to NULL failed");
728
729   GST_DEBUG ("checking refcount");
730   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
731   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
732   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
733
734   GST_DEBUG ("cleanup");
735   gst_object_unref (bus);
736   gst_object_unref (pipeline);
737 }
738
739 GST_END_TEST;
740
741 GST_START_TEST (test_children_state_change_order_two_sink)
742 {
743   GstElement *src, *tee, *identity, *sink1, *sink2, *pipeline;
744   GstStateChangeReturn ret;
745   GstBus *bus;
746
747   pipeline = gst_pipeline_new (NULL);
748   fail_unless (pipeline != NULL, "Could not create pipeline");
749
750   bus = gst_element_get_bus (pipeline);
751   fail_unless (bus != NULL, "Pipeline has no bus?!");
752
753   src = gst_element_factory_make ("fakesrc", NULL);
754   fail_if (src == NULL, "Could not create fakesrc");
755
756   tee = gst_element_factory_make ("tee", NULL);
757   fail_if (tee == NULL, "Could not create tee");
758
759   identity = gst_element_factory_make ("identity", NULL);
760   fail_if (identity == NULL, "Could not create identity");
761
762   sink1 = gst_element_factory_make ("fakesink", NULL);
763   fail_if (sink1 == NULL, "Could not create fakesink1");
764
765   sink2 = gst_element_factory_make ("fakesink", NULL);
766   fail_if (sink2 == NULL, "Could not create fakesink2");
767
768   gst_bin_add_many (GST_BIN (pipeline), src, tee, identity, sink1, sink2, NULL);
769
770   fail_unless (gst_element_link (src, tee) == TRUE);
771   fail_unless (gst_element_link (tee, identity) == TRUE);
772   fail_unless (gst_element_link (identity, sink1) == TRUE);
773   fail_unless (gst_element_link (tee, sink2) == TRUE);
774
775   ret = gst_element_set_state (pipeline, GST_STATE_READY);
776   fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to READY failed");
777
778   /* NULL => READY */
779   {
780     GstMessage *msg;
781     GstState old = 0, new = 0, pending = 0;
782     GstObject *first, *second;
783
784     msg = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, GST_SECOND);
785     fail_if (msg == NULL, "No state change message within 1 second (#201)");
786
787     gst_message_parse_state_changed (msg, &old, &new, &pending);
788     first = gst_object_ref (msg->src);
789
790     fail_if (first != GST_OBJECT (sink1) && first != GST_OBJECT (sink2),
791         "sink1 or sink2 should have changed state next #(202)");
792     gst_message_unref (msg);
793
794     msg = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, GST_SECOND);
795     fail_if (msg == NULL, "No state change message within 1 second (#201)");
796
797     gst_message_parse_state_changed (msg, &old, &new, &pending);
798     second = gst_object_ref (msg->src);
799
800     fail_if (second != GST_OBJECT (sink1) && second != GST_OBJECT (sink2),
801         "sink1 or sink2 should have changed state next #(202)");
802     gst_message_unref (msg);
803
804     fail_if (second == first, "got state change from same object");
805
806     gst_object_unref (first);
807     gst_object_unref (second);
808   }
809   ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_NULL, GST_STATE_READY, 203);
810   ASSERT_STATE_CHANGE_MSG (bus, tee, GST_STATE_NULL, GST_STATE_READY, 204);
811   ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_NULL, GST_STATE_READY, 205);
812   ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_NULL, GST_STATE_READY, 206);
813
814   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
815   ASSERT_OBJECT_REFCOUNT (tee, "tee", 1);
816   ASSERT_OBJECT_REFCOUNT (identity, "identity", 1);
817   ASSERT_OBJECT_REFCOUNT (sink1, "sink1", 1);
818   ASSERT_OBJECT_REFCOUNT (sink2, "sink2", 1);
819   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
820
821   ret = gst_element_set_state (pipeline, GST_STATE_NULL);
822   fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to NULL failed");
823
824   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
825   ASSERT_OBJECT_REFCOUNT (tee, "tee", 1);
826   ASSERT_OBJECT_REFCOUNT (identity, "identity", 1);
827   ASSERT_OBJECT_REFCOUNT (sink1, "sink1", 1);
828   ASSERT_OBJECT_REFCOUNT (sink2, "sink2", 1);
829   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
830
831   gst_object_unref (bus);
832   gst_object_unref (pipeline);
833 }
834
835 GST_END_TEST;
836
837 GST_START_TEST (test_iterate_sorted)
838 {
839   GstElement *src, *tee, *identity, *sink1, *sink2, *pipeline, *bin;
840   GstIterator *it;
841   gpointer elem;
842
843   pipeline = gst_pipeline_new (NULL);
844   fail_unless (pipeline != NULL, "Could not create pipeline");
845
846   bin = gst_bin_new (NULL);
847   fail_unless (bin != NULL, "Could not create bin");
848
849   src = gst_element_factory_make ("fakesrc", NULL);
850   fail_if (src == NULL, "Could not create fakesrc");
851
852   tee = gst_element_factory_make ("tee", NULL);
853   fail_if (tee == NULL, "Could not create tee");
854
855   sink1 = gst_element_factory_make ("fakesink", NULL);
856   fail_if (sink1 == NULL, "Could not create fakesink1");
857
858   gst_bin_add_many (GST_BIN (bin), src, tee, sink1, NULL);
859
860   fail_unless (gst_element_link (src, tee) == TRUE);
861   fail_unless (gst_element_link (tee, sink1) == TRUE);
862
863   identity = gst_element_factory_make ("identity", NULL);
864   fail_if (identity == NULL, "Could not create identity");
865
866   sink2 = gst_element_factory_make ("fakesink", NULL);
867   fail_if (sink2 == NULL, "Could not create fakesink2");
868
869   gst_bin_add_many (GST_BIN (pipeline), bin, identity, sink2, NULL);
870
871   fail_unless (gst_element_link (tee, identity) == TRUE);
872   fail_unless (gst_element_link (identity, sink2) == TRUE);
873
874   it = gst_bin_iterate_sorted (GST_BIN (pipeline));
875   fail_unless (gst_iterator_next (it, &elem) == GST_ITERATOR_OK);
876   fail_unless (elem == sink2);
877   gst_object_unref (elem);
878
879   fail_unless (gst_iterator_next (it, &elem) == GST_ITERATOR_OK);
880   fail_unless (elem == identity);
881   gst_object_unref (elem);
882
883   fail_unless (gst_iterator_next (it, &elem) == GST_ITERATOR_OK);
884   fail_unless (elem == bin);
885   gst_object_unref (elem);
886
887   gst_iterator_free (it);
888
889   gst_object_unref (pipeline);
890 }
891
892 GST_END_TEST;
893
894 static Suite *
895 gst_bin_suite (void)
896 {
897   Suite *s = suite_create ("GstBin");
898   TCase *tc_chain = tcase_create ("bin tests");
899
900   tcase_set_timeout (tc_chain, 0);
901
902   suite_add_tcase (s, tc_chain);
903   tcase_add_test (tc_chain, test_interface);
904   tcase_add_test (tc_chain, test_children_state_change_order_flagged_sink);
905   tcase_add_test (tc_chain, test_children_state_change_order_semi_sink);
906   tcase_add_test (tc_chain, test_children_state_change_order_two_sink);
907   tcase_add_test (tc_chain, test_message_state_changed);
908   tcase_add_test (tc_chain, test_message_state_changed_child);
909   tcase_add_test (tc_chain, test_message_state_changed_children);
910   tcase_add_test (tc_chain, test_watch_for_state_change);
911   tcase_add_test (tc_chain, test_add_linked);
912   tcase_add_test (tc_chain, test_add_self);
913   tcase_add_test (tc_chain, test_iterate_sorted);
914
915   return s;
916 }
917
918 GST_CHECK_MAIN (gst_bin);