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