3427010abe561450ab4ef009ed6b04df99bdc297
[platform/upstream/gstreamer.git] / 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_messages (GstBus * bus, int count)
27 {
28   GstMessage *message;
29
30   int i;
31
32   GST_DEBUG ("popping %d messages", count);
33   for (i = 0; i < count; ++i) {
34     message = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, -1);
35
36     fail_unless (message && GST_MESSAGE_TYPE (message)
37         == GST_MESSAGE_STATE_CHANGED, "did not get GST_MESSAGE_STATE_CHANGED");
38
39     gst_message_unref (message);
40   }
41   GST_DEBUG ("popped %d messages", count);
42 }
43
44 GST_START_TEST (test_interface)
45 {
46   GstBin *bin, *bin2;
47   GstElement *filesrc;
48   GstIterator *it;
49   gpointer item;
50
51   bin = GST_BIN (gst_bin_new (NULL));
52   fail_unless (bin != NULL, "Could not create bin");
53
54   filesrc = gst_element_factory_make ("filesrc", NULL);
55   fail_unless (filesrc != NULL, "Could not create filesrc");
56   fail_unless (GST_IS_URI_HANDLER (filesrc), "Filesrc not a URI handler");
57   gst_bin_add (bin, filesrc);
58
59   fail_unless (gst_bin_get_by_interface (bin, GST_TYPE_URI_HANDLER) == filesrc);
60   it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER);
61   fail_unless (it != NULL);
62   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
63   fail_unless (item == (gpointer) filesrc);
64   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
65   gst_iterator_free (it);
66
67   gst_bin_add_many (bin,
68       gst_element_factory_make ("identity", NULL),
69       gst_element_factory_make ("identity", NULL),
70       gst_element_factory_make ("identity", NULL), NULL);
71   fail_unless (gst_bin_get_by_interface (bin, GST_TYPE_URI_HANDLER) == filesrc);
72   it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER);
73   fail_unless (it != NULL);
74   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
75   fail_unless (item == (gpointer) filesrc);
76   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
77   gst_iterator_free (it);
78
79   bin2 = bin;
80   bin = GST_BIN (gst_bin_new (NULL));
81   fail_unless (bin != NULL);
82   gst_bin_add_many (bin,
83       gst_element_factory_make ("identity", NULL),
84       gst_element_factory_make ("identity", NULL),
85       GST_ELEMENT (bin2), gst_element_factory_make ("identity", NULL), NULL);
86   fail_unless (gst_bin_get_by_interface (bin, GST_TYPE_URI_HANDLER) == filesrc);
87   it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER);
88   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
89   fail_unless (item == (gpointer) filesrc);
90   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
91   gst_iterator_free (it);
92
93   gst_bin_add (bin, gst_element_factory_make ("filesrc", NULL));
94   gst_bin_add (bin2, gst_element_factory_make ("filesrc", NULL));
95   it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER);
96   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
97   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
98   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
99   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
100   gst_iterator_free (it);
101
102   gst_object_unref (bin);
103 }
104
105 GST_END_TEST;
106
107 GST_START_TEST (test_message_state_changed)
108 {
109   GstBin *bin;
110   GstBus *bus;
111   GstMessage *message;
112
113   bin = GST_BIN (gst_bin_new (NULL));
114   fail_unless (bin != NULL, "Could not create bin");
115   ASSERT_OBJECT_REFCOUNT (bin, "bin", 1);
116
117   bus = GST_ELEMENT_BUS (bin);
118
119   /* change state, spawning a message, causing an incref on the bin */
120   gst_element_set_state (GST_ELEMENT (bin), GST_STATE_READY);
121
122   ASSERT_OBJECT_REFCOUNT (bin, "bin", 2);
123
124   /* get and unref the message, causing a decref on the bin */
125   message = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, -1);
126
127   fail_unless (message && GST_MESSAGE_TYPE (message)
128       == GST_MESSAGE_STATE_CHANGED, "did not get GST_MESSAGE_STATE_CHANGED");
129
130   gst_message_unref (message);
131
132   ASSERT_OBJECT_REFCOUNT (bin, "bin", 1);
133
134   /* clean up */
135   gst_object_unref (bin);
136 }
137
138 GST_END_TEST;
139
140 GST_START_TEST (test_message_state_changed_child)
141 {
142   GstBin *bin;
143   GstElement *src;
144   GstBus *bus;
145   GstMessage *message;
146
147   bin = GST_BIN (gst_bin_new (NULL));
148   fail_unless (bin != NULL, "Could not create bin");
149   ASSERT_OBJECT_REFCOUNT (bin, "bin", 1);
150
151   src = gst_element_factory_make ("fakesrc", NULL);
152   fail_if (src == NULL, "Could not create fakesrc");
153   gst_bin_add (bin, src);
154   ASSERT_OBJECT_REFCOUNT (bin, "bin", 1);
155   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
156
157   bus = GST_ELEMENT_BUS (bin);
158
159   /* change state, spawning two messages:
160    * - first for fakesrc, forwarded to bin's bus, causing incref on fakesrc
161    * - second for bin, causing an incref on the bin */
162   GST_DEBUG ("setting bin to READY");
163   fail_unless (gst_element_set_state (GST_ELEMENT (bin), GST_STATE_READY)
164       == GST_STATE_CHANGE_SUCCESS);
165
166   ASSERT_OBJECT_REFCOUNT (src, "src", 2);
167   ASSERT_OBJECT_REFCOUNT (bin, "bin", 2);
168
169   /* get and unref the message, causing a decref on the src */
170   message = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, -1);
171   fail_unless (message && GST_MESSAGE_TYPE (message)
172       == GST_MESSAGE_STATE_CHANGED, "did not get GST_MESSAGE_STATE_CHANGED");
173
174   fail_unless (message->src == GST_OBJECT (src));
175   gst_message_unref (message);
176
177   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
178   ASSERT_OBJECT_REFCOUNT (bin, "bin", 2);
179
180   /* get and unref message 2, causing a decref on the bin */
181   message = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, -1);
182   fail_unless (message && GST_MESSAGE_TYPE (message)
183       == GST_MESSAGE_STATE_CHANGED, "did not get GST_MESSAGE_STATE_CHANGED");
184
185   fail_unless (message->src == GST_OBJECT (bin));
186   gst_message_unref (message);
187
188   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
189   ASSERT_OBJECT_REFCOUNT (bin, "bin", 1);
190
191   /* clean up */
192   gst_object_unref (bin);
193 }
194
195 GST_END_TEST;
196
197 GST_START_TEST (test_message_state_changed_children)
198 {
199   GstPipeline *pipeline;
200   GstElement *src, *sink;
201   GstBus *bus;
202
203   pipeline = GST_PIPELINE (gst_pipeline_new (NULL));
204   fail_unless (pipeline != NULL, "Could not create pipeline");
205   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
206
207   src = gst_element_factory_make ("fakesrc", NULL);
208   fail_if (src == NULL, "Could not create fakesrc");
209   /* need to silence the element as the deep_notify refcounts the
210    * parents while running */
211   g_object_set (G_OBJECT (src), "silent", TRUE, NULL);
212   gst_bin_add (GST_BIN (pipeline), src);
213
214   sink = gst_element_factory_make ("fakesink", NULL);
215   /* need to silence the element as the deep_notify refcounts the
216    * parents while running */
217   g_object_set (G_OBJECT (sink), "silent", TRUE, NULL);
218   fail_if (sink == NULL, "Could not create fakesink");
219   gst_bin_add (GST_BIN (pipeline), sink);
220
221   fail_unless (gst_element_link (src, sink), "could not link src and sink");
222
223   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
224   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
225   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
226
227   bus = GST_ELEMENT_BUS (pipeline);
228
229   /* change state to READY, spawning three messages */
230   GST_DEBUG ("setting pipeline to READY");
231   fail_unless (gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_READY)
232       == GST_STATE_CHANGE_SUCCESS);
233
234   /* each object is referenced by a message */
235   ASSERT_OBJECT_REFCOUNT (bus, "bus", 1);
236   ASSERT_OBJECT_REFCOUNT (src, "src", 2);
237   ASSERT_OBJECT_REFCOUNT (sink, "sink", 2);
238   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 2);
239
240   pop_messages (bus, 3);
241   fail_if ((gst_bus_pop (bus)) != NULL);
242
243   ASSERT_OBJECT_REFCOUNT (bus, "bus", 1);
244   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
245   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
246   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
247
248   /* change state to PAUSED, spawning three messages */
249   GST_DEBUG ("setting pipeline to PAUSED");
250   fail_unless (gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PAUSED)
251       == GST_STATE_CHANGE_SUCCESS);
252
253   /* each object is referenced by a message;
254    * base_sink_chain has taken a refcount on the sink, and is blocked on
255    * preroll */
256   ASSERT_OBJECT_REFCOUNT (src, "src", 2);
257   ASSERT_OBJECT_REFCOUNT (sink, "sink", 3);
258   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 2);
259
260   pop_messages (bus, 3);
261   fail_if ((gst_bus_pop (bus)) != NULL);
262
263   ASSERT_OBJECT_REFCOUNT (bus, "bus", 1);
264   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
265   ASSERT_OBJECT_REFCOUNT (sink, "sink", 2);
266   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
267
268   /* change state to PLAYING, spawning three messages */
269   GST_DEBUG ("setting pipeline to PLAYING");
270   fail_unless (gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING)
271       == GST_STATE_CHANGE_SUCCESS);
272
273   /* each object is referenced by one message
274    * sink might have an extra reference if it's still blocked on preroll */
275   ASSERT_OBJECT_REFCOUNT (src, "src", 2);
276   ASSERT_OBJECT_REFCOUNT_BETWEEN (sink, "sink", 2, 3);
277   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 2);
278
279   pop_messages (bus, 3);
280   fail_if ((gst_bus_pop (bus)) != NULL);
281
282   ASSERT_OBJECT_REFCOUNT (bus, "bus", 1);
283   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
284   /* sink might have an extra reference if it's still blocked on preroll */
285   ASSERT_OBJECT_REFCOUNT_BETWEEN (sink, "sink", 1, 2);
286   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
287
288   /* go back to READY, spawning six messages */
289   GST_DEBUG ("setting pipeline to READY");
290   fail_unless (gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_READY)
291       == GST_STATE_CHANGE_SUCCESS);
292
293   /* each object is referenced by two messages */
294   ASSERT_OBJECT_REFCOUNT (src, "src", 3);
295   ASSERT_OBJECT_REFCOUNT (sink, "sink", 3);
296   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 3);
297
298   pop_messages (bus, 6);
299   fail_if ((gst_bus_pop (bus)) != NULL);
300
301   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
302   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
303   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
304
305   /* setting pipeline to NULL flushes the bus automatically */
306   fail_unless (gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL)
307       == GST_STATE_CHANGE_SUCCESS);
308
309   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
310   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
311   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
312
313   /* clean up */
314   gst_object_unref (pipeline);
315 }
316
317 GST_END_TEST;
318
319 GST_START_TEST (test_watch_for_state_change)
320 {
321   GstElement *src, *sink, *bin;
322   GstBus *bus;
323
324   bin = gst_element_factory_make ("bin", NULL);
325   fail_unless (bin != NULL, "Could not create bin");
326
327   src = gst_element_factory_make ("fakesrc", NULL);
328   fail_if (src == NULL, "Could not create fakesrc");
329   sink = gst_element_factory_make ("fakesink", NULL);
330   fail_if (sink == NULL, "Could not create fakesink");
331
332   gst_bin_add (GST_BIN (bin), sink);
333   gst_bin_add (GST_BIN (bin), src);
334
335   fail_unless (gst_element_link (src, sink), "could not link src and sink");
336
337   bus = GST_ELEMENT_BUS (bin);
338
339   /* change state, spawning two times three messages, minus one async */
340   fail_unless (gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED)
341       == GST_STATE_CHANGE_ASYNC);
342
343   pop_messages (bus, 5);
344
345   fail_unless (gst_bus_have_pending (bus, GST_MESSAGE_ANY) == FALSE,
346       "Unexpected messages on bus");
347
348   gst_bin_watch_for_state_change (GST_BIN (bin));
349
350   /* should get the bin's state change message now */
351   pop_messages (bus, 1);
352
353   fail_unless (gst_bus_have_pending (bus, GST_MESSAGE_ANY) == FALSE,
354       "Unexpected messages on bus");
355
356   fail_unless (gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PLAYING)
357       == GST_STATE_CHANGE_SUCCESS);
358
359   pop_messages (bus, 3);
360
361   /* this one might return either SUCCESS or ASYNC, likely SUCCESS */
362   gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED);
363
364   gst_bin_watch_for_state_change (GST_BIN (bin));
365
366   pop_messages (bus, 3);
367
368   fail_unless (gst_bus_have_pending (bus, GST_MESSAGE_ANY) == FALSE,
369       "Unexpected messages on bus");
370
371   /* setting bin to NULL flushes the bus automatically */
372   fail_unless (gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL)
373       == GST_STATE_CHANGE_SUCCESS);
374
375   /* clean up */
376   gst_object_unref (bin);
377 }
378
379 GST_END_TEST;
380
381 /* adding an element with linked pads to a bin unlinks the
382  * pads */
383 GST_START_TEST (test_add_linked)
384 {
385   GstElement *src, *sink;
386   GstPad *srcpad, *sinkpad;
387   GstElement *pipeline;
388
389   pipeline = gst_pipeline_new (NULL);
390   fail_unless (pipeline != NULL, "Could not create pipeline");
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   srcpad = gst_element_get_pad (src, "src");
398   fail_unless (srcpad != NULL);
399   sinkpad = gst_element_get_pad (sink, "sink");
400   fail_unless (sinkpad != NULL);
401
402   fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK);
403
404   /* pads are linked now */
405   fail_unless (gst_pad_is_linked (srcpad));
406   fail_unless (gst_pad_is_linked (sinkpad));
407
408   /* adding element to bin voids hierarchy so pads are unlinked */
409   gst_bin_add (GST_BIN (pipeline), src);
410
411   /* check if pads really are unlinked */
412   fail_unless (!gst_pad_is_linked (srcpad));
413   fail_unless (!gst_pad_is_linked (sinkpad));
414
415   /* cannot link pads in wrong hierarchy */
416   fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_WRONG_HIERARCHY);
417
418   /* adding other element to bin as well */
419   gst_bin_add (GST_BIN (pipeline), sink);
420
421   /* now we can link again */
422   fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK);
423
424   /* check if pads really are linked */
425   fail_unless (gst_pad_is_linked (srcpad));
426   fail_unless (gst_pad_is_linked (sinkpad));
427
428   gst_object_unref (srcpad);
429   gst_object_unref (sinkpad);
430   gst_object_unref (pipeline);
431 }
432
433 GST_END_TEST;
434
435 /* g_print ("%10s: %4d => %4d\n", GST_OBJECT_NAME (msg->src), old, new); */
436
437 #define ASSERT_STATE_CHANGE_MSG(bus,element,old_state,new_state,num)          \
438   {                                                                           \
439     GstMessage *msg;                                                          \
440     GstState old = 0, new = 0;                                                \
441     msg = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, GST_SECOND);          \
442     fail_if (msg == NULL, "No state change message within 1 second (#"        \
443         G_STRINGIFY (num) ")");                                               \
444     gst_message_parse_state_changed (msg, &old, &new);                        \
445     fail_if (msg->src != GST_OBJECT (element), G_STRINGIFY(element)           \
446         " should have changed state next (#" G_STRINGIFY (num) ")");          \
447     fail_if (old != old_state || new != new_state, "state change is not "     \
448         G_STRINGIFY (old_state) " => " G_STRINGIFY (new_state));              \
449     gst_message_unref (msg);                                                  \
450   }
451
452 GST_START_TEST (test_children_state_change_order_flagged_sink)
453 {
454   GstElement *src, *identity, *sink, *pipeline;
455   GstStateChangeReturn ret;
456   GstBus *bus;
457
458   pipeline = gst_pipeline_new (NULL);
459   fail_unless (pipeline != NULL, "Could not create pipeline");
460
461   bus = GST_ELEMENT_BUS (pipeline);
462   fail_unless (bus != NULL, "Pipeline has no bus?!");
463
464   src = gst_element_factory_make ("fakesrc", NULL);
465   fail_if (src == NULL, "Could not create fakesrc");
466
467   identity = gst_element_factory_make ("identity", NULL);
468   fail_if (identity == NULL, "Could not create identity");
469
470   sink = gst_element_factory_make ("fakesink", NULL);
471   fail_if (sink == NULL, "Could not create fakesink");
472
473   gst_bin_add_many (GST_BIN (pipeline), src, identity, sink, NULL);
474
475   fail_unless (gst_element_link (src, identity) == TRUE);
476   fail_unless (gst_element_link (identity, sink) == TRUE);
477
478   /* (1) Test state change with fakesink being a regular sink */
479   ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
480   fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to PLAYING failed");
481
482   /* NULL => READY */
483   ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_NULL, GST_STATE_READY, 101);
484   ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_NULL, GST_STATE_READY, 102);
485   ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_NULL, GST_STATE_READY, 103);
486   ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_NULL, GST_STATE_READY, 104);
487
488   /* READY => PAUSED */
489   /* because of pre-rolling, sink will return ASYNC on state 
490    * change and change state later when it has a buffer */
491   ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_READY, GST_STATE_PAUSED,
492       105);
493 #if 0
494   /* From here on, all bets are off. Usually the source changes state next,
495    * but it might just as well be that the first buffer produced by the 
496    * source reaches the sink before the source has finished its state change,
497    * in which case the sink will commit its new state before the source ...  */
498   ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_READY, GST_STATE_PAUSED, 106);
499   ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_READY, GST_STATE_PAUSED, 107);
500   ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_READY, GST_STATE_PAUSED,
501       108);
502
503   /* PAUSED => PLAYING */
504   ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_PAUSED, GST_STATE_PLAYING, 109);
505   ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_PAUSED, GST_STATE_PLAYING,
506       110);
507   ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_PAUSED, GST_STATE_PLAYING, 111);
508   ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_PAUSED, GST_STATE_PLAYING,
509       112);
510 #else
511   pop_messages (bus, 3);        /* pop remaining ready => paused messages off the bus */
512   pop_messages (bus, 4);        /* pop paused => playing messages off the bus */
513 #endif
514
515   /* don't set to NULL that will set the bus flushing and kill our messages */
516   ret = gst_element_set_state (pipeline, GST_STATE_READY);
517   fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to READY failed");
518
519   /* TODO: do we need to check downwards state change order as well? */
520   pop_messages (bus, 4);        /* pop playing => paused messages off the bus */
521   pop_messages (bus, 4);        /* pop paused => ready messages off the bus */
522
523   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
524   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
525   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
526
527   ret = gst_element_set_state (pipeline, GST_STATE_NULL);
528   fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to NULL failed");
529
530   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
531   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
532   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
533
534   gst_object_unref (pipeline);
535 }
536
537 GST_END_TEST;
538
539
540 GST_START_TEST (test_children_state_change_order_semi_sink)
541 {
542   GstElement *src, *identity, *sink, *pipeline;
543   GstStateChangeReturn ret;
544   GstBus *bus;
545
546   /* (2) Now again, but check other code path where we don't have
547    *     a proper sink correctly flagged as such, but a 'semi-sink' */
548   pipeline = gst_pipeline_new (NULL);
549   fail_unless (pipeline != NULL, "Could not create pipeline");
550
551   bus = GST_ELEMENT_BUS (pipeline);
552   fail_unless (bus != NULL, "Pipeline has no bus?!");
553
554   src = gst_element_factory_make ("fakesrc", NULL);
555   fail_if (src == NULL, "Could not create fakesrc");
556
557   identity = gst_element_factory_make ("identity", NULL);
558   fail_if (identity == NULL, "Could not create identity");
559
560   sink = gst_element_factory_make ("fakesink", NULL);
561   fail_if (sink == NULL, "Could not create fakesink");
562
563   gst_bin_add_many (GST_BIN (pipeline), src, identity, sink, NULL);
564
565   fail_unless (gst_element_link (src, identity) == TRUE);
566   fail_unless (gst_element_link (identity, sink) == TRUE);
567
568   /* this is not very nice but should work just fine in this case. */
569   GST_FLAG_UNSET (sink, GST_ELEMENT_IS_SINK);   /* <======== */
570
571   ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
572   fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to PLAYING failed");
573
574   /* NULL => READY */
575   ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_NULL, GST_STATE_READY, 201);
576   ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_NULL, GST_STATE_READY, 202);
577   ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_NULL, GST_STATE_READY, 203);
578   ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_NULL, GST_STATE_READY, 204);
579
580   /* READY => PAUSED */
581   /* because of pre-rolling, sink will return ASYNC on state 
582    * change and change state later when it has a buffer */
583   ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_READY, GST_STATE_PAUSED,
584       205);
585 #if 0
586   /* From here on, all bets are off. Usually the source changes state next,
587    * but it might just as well be that the first buffer produced by the 
588    * source reaches the sink before the source has finished its state change,
589    * in which case the sink will commit its new state before the source ...  */
590   ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_READY, GST_STATE_PAUSED, 206);
591   ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_READY, GST_STATE_PAUSED, 207);
592   ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_READY, GST_STATE_PAUSED,
593       208);
594
595   /* PAUSED => PLAYING */
596   ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_PAUSED, GST_STATE_PLAYING, 209);
597   ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_PAUSED, GST_STATE_PLAYING,
598       210);
599   ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_PAUSED, GST_STATE_PLAYING, 211);
600   ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_PAUSED, GST_STATE_PLAYING,
601       212);
602 #else
603   pop_messages (bus, 3);        /* pop remaining ready => paused messages off the bus */
604   pop_messages (bus, 4);        /* pop paused => playing messages off the bus */
605 #endif
606
607   /* don't set to NULL that will set the bus flushing and kill our messages */
608   ret = gst_element_set_state (pipeline, GST_STATE_READY);
609   fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to READY failed");
610
611   /* TODO: do we need to check downwards state change order as well? */
612   pop_messages (bus, 4);        /* pop playing => paused messages off the bus */
613   pop_messages (bus, 4);        /* pop paused => ready messages off the bus */
614
615   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
616   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
617   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
618
619   ret = gst_element_set_state (pipeline, GST_STATE_NULL);
620   fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to NULL failed");
621
622   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
623   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
624   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
625
626   gst_object_unref (pipeline);
627 }
628
629 GST_END_TEST;
630
631 GST_START_TEST (test_children_state_change_order_two_sink)
632 {
633   GstElement *src, *tee, *identity, *sink1, *sink2, *pipeline;
634   GstStateChangeReturn ret;
635   GstBus *bus;
636
637   pipeline = gst_pipeline_new (NULL);
638   fail_unless (pipeline != NULL, "Could not create pipeline");
639
640   bus = GST_ELEMENT_BUS (pipeline);
641   fail_unless (bus != NULL, "Pipeline has no bus?!");
642
643   src = gst_element_factory_make ("fakesrc", NULL);
644   fail_if (src == NULL, "Could not create fakesrc");
645
646   tee = gst_element_factory_make ("tee", NULL);
647   fail_if (tee == NULL, "Could not create tee");
648
649   identity = gst_element_factory_make ("identity", NULL);
650   fail_if (identity == NULL, "Could not create identity");
651
652   sink1 = gst_element_factory_make ("fakesink", NULL);
653   fail_if (sink1 == NULL, "Could not create fakesink1");
654
655   sink2 = gst_element_factory_make ("fakesink", NULL);
656   fail_if (sink2 == NULL, "Could not create fakesink2");
657
658   gst_bin_add_many (GST_BIN (pipeline), src, tee, identity, sink1, sink2, NULL);
659
660   fail_unless (gst_element_link (src, tee) == TRUE);
661   fail_unless (gst_element_link (tee, identity) == TRUE);
662   fail_unless (gst_element_link (identity, sink1) == TRUE);
663   fail_unless (gst_element_link (tee, sink2) == TRUE);
664
665   ret = gst_element_set_state (pipeline, GST_STATE_READY);
666   fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to READY failed");
667
668   /* NULL => READY */
669   {
670     GstMessage *msg;
671     GstState old = 0, new = 0;
672     GstObject *first, *second;
673
674     msg = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, GST_SECOND);
675     fail_if (msg == NULL, "No state change message within 1 second (#201)");
676
677     gst_message_parse_state_changed (msg, &old, &new);
678     first = gst_object_ref (msg->src);
679
680     fail_if (first != GST_OBJECT (sink1) && first != GST_OBJECT (sink2),
681         "sink1 or sink2 should have changed state next #(202)");
682     gst_message_unref (msg);
683
684     msg = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, GST_SECOND);
685     fail_if (msg == NULL, "No state change message within 1 second (#201)");
686
687     gst_message_parse_state_changed (msg, &old, &new);
688     second = gst_object_ref (msg->src);
689
690     fail_if (second != GST_OBJECT (sink1) && second != GST_OBJECT (sink2),
691         "sink1 or sink2 should have changed state next #(202)");
692     gst_message_unref (msg);
693
694     fail_if (second == first, "got state change from same object");
695
696     gst_object_unref (first);
697     gst_object_unref (second);
698   }
699   ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_NULL, GST_STATE_READY, 203);
700   ASSERT_STATE_CHANGE_MSG (bus, tee, GST_STATE_NULL, GST_STATE_READY, 204);
701   ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_NULL, GST_STATE_READY, 205);
702   ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_NULL, GST_STATE_READY, 206);
703
704   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
705   ASSERT_OBJECT_REFCOUNT (tee, "tee", 1);
706   ASSERT_OBJECT_REFCOUNT (identity, "identity", 1);
707   ASSERT_OBJECT_REFCOUNT (sink1, "sink1", 1);
708   ASSERT_OBJECT_REFCOUNT (sink2, "sink2", 1);
709   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
710
711   ret = gst_element_set_state (pipeline, GST_STATE_NULL);
712   fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to NULL failed");
713
714   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
715   ASSERT_OBJECT_REFCOUNT (tee, "tee", 1);
716   ASSERT_OBJECT_REFCOUNT (identity, "identity", 1);
717   ASSERT_OBJECT_REFCOUNT (sink1, "sink1", 1);
718   ASSERT_OBJECT_REFCOUNT (sink2, "sink2", 1);
719   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
720
721   gst_object_unref (pipeline);
722 }
723
724 GST_END_TEST;
725
726 Suite *
727 gst_bin_suite (void)
728 {
729   Suite *s = suite_create ("GstBin");
730   TCase *tc_chain = tcase_create ("bin tests");
731
732   suite_add_tcase (s, tc_chain);
733   tcase_add_test (tc_chain, test_interface);
734   tcase_add_test (tc_chain, test_children_state_change_order_flagged_sink);
735   tcase_add_test (tc_chain, test_children_state_change_order_semi_sink);
736   tcase_add_test (tc_chain, test_children_state_change_order_two_sink);
737   tcase_add_test (tc_chain, test_message_state_changed);
738   tcase_add_test (tc_chain, test_message_state_changed_child);
739   tcase_add_test (tc_chain, test_message_state_changed_children);
740   tcase_add_test (tc_chain, test_watch_for_state_change);
741   tcase_add_test (tc_chain, test_add_linked);
742
743   return s;
744 }
745
746 int
747 main (int argc, char **argv)
748 {
749   int nf;
750
751   Suite *s = gst_bin_suite ();
752   SRunner *sr = srunner_create (s);
753
754   gst_check_init (&argc, &argv);
755
756   srunner_run_all (sr, CK_NORMAL);
757   nf = srunner_ntests_failed (sr);
758   srunner_free (sr);
759
760   return nf;
761 }