bin: port unit test to 0.11
[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   GValue item = { 0, };
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 (g_value_get_object (&item) == (gpointer) filesrc);
81   g_value_reset (&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 (g_value_get_object (&item) == (gpointer) filesrc);
93   g_value_reset (&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 (g_value_get_object (&item) == (gpointer) filesrc);
107   g_value_reset (&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   g_value_reset (&item);
116   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
117   g_value_reset (&item);
118   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
119   g_value_reset (&item);
120   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
121   g_value_unset (&item);
122   gst_iterator_free (it);
123
124   gst_object_unref (bin);
125 }
126
127 GST_END_TEST;
128
129 GST_START_TEST (test_message_state_changed)
130 {
131   GstBin *bin;
132   GstBus *bus;
133   GstMessage *message;
134   GstStateChangeReturn ret;
135
136   bin = GST_BIN (gst_bin_new (NULL));
137   fail_unless (bin != NULL, "Could not create bin");
138   ASSERT_OBJECT_REFCOUNT (bin, "bin", 1);
139
140   bus = g_object_new (gst_bus_get_type (), NULL);
141   gst_element_set_bus (GST_ELEMENT_CAST (bin), bus);
142
143   /* change state, spawning a message, causing an incref on the bin */
144   ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_READY);
145   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
146
147   ASSERT_OBJECT_REFCOUNT (bin, "bin", 2);
148
149   /* get and unref the message, causing a decref on the bin */
150   message = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, -1);
151
152   fail_unless (message && GST_MESSAGE_TYPE (message)
153       == GST_MESSAGE_STATE_CHANGED, "did not get GST_MESSAGE_STATE_CHANGED");
154
155   gst_message_unref (message);
156
157   ASSERT_OBJECT_REFCOUNT (bin, "bin", 1);
158
159   /* clean up */
160   ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL);
161   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
162
163   gst_object_unref (bus);
164   gst_object_unref (bin);
165 }
166
167 GST_END_TEST;
168
169 GST_START_TEST (test_message_state_changed_child)
170 {
171   GstBin *bin;
172   GstElement *src;
173   GstBus *bus;
174   GstMessage *message;
175   GstStateChangeReturn ret;
176
177   bin = GST_BIN (gst_bin_new (NULL));
178   fail_unless (bin != NULL, "Could not create bin");
179   ASSERT_OBJECT_REFCOUNT (bin, "bin", 1);
180
181   bus = g_object_new (gst_bus_get_type (), NULL);
182   gst_element_set_bus (GST_ELEMENT_CAST (bin), bus);
183
184   src = gst_element_factory_make ("fakesrc", NULL);
185   fail_if (src == NULL, "Could not create fakesrc");
186   gst_bin_add (bin, src);
187   ASSERT_OBJECT_REFCOUNT (bin, "bin", 1);
188   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
189
190   /* change state, spawning two messages:
191    * - first for fakesrc, forwarded to bin's bus, causing incref on fakesrc
192    * - second for bin, causing an incref on the bin */
193   GST_DEBUG ("setting bin to READY");
194   ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_READY);
195   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
196
197   ASSERT_OBJECT_REFCOUNT (src, "src", 2);
198   ASSERT_OBJECT_REFCOUNT (bin, "bin", 2);
199
200   /* get and unref the message, causing a decref on the src */
201   message = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, -1);
202   fail_unless (message && GST_MESSAGE_TYPE (message)
203       == GST_MESSAGE_STATE_CHANGED, "did not get GST_MESSAGE_STATE_CHANGED");
204
205   fail_unless (message->src == GST_OBJECT (src));
206   gst_message_unref (message);
207
208   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
209   ASSERT_OBJECT_REFCOUNT (bin, "bin", 2);
210
211   /* get and unref message 2, causing a decref on the bin */
212   message = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, -1);
213   fail_unless (message && GST_MESSAGE_TYPE (message)
214       == GST_MESSAGE_STATE_CHANGED, "did not get GST_MESSAGE_STATE_CHANGED");
215
216   fail_unless (message->src == GST_OBJECT (bin));
217   gst_message_unref (message);
218
219   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
220   ASSERT_OBJECT_REFCOUNT (bin, "bin", 1);
221
222   /* clean up */
223   ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL);
224   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
225   gst_object_unref (bus);
226   gst_object_unref (bin);
227 }
228
229 GST_END_TEST;
230
231 GST_START_TEST (test_message_state_changed_children)
232 {
233   GstPipeline *pipeline;
234   GstElement *src, *sink;
235   GstBus *bus;
236   GstStateChangeReturn ret;
237   GstState current, pending;
238
239   pipeline = GST_PIPELINE (gst_pipeline_new (NULL));
240   fail_unless (pipeline != NULL, "Could not create pipeline");
241   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
242
243   src = gst_element_factory_make ("fakesrc", NULL);
244   fail_if (src == NULL, "Could not create fakesrc");
245   /* need to silence the element as the deep_notify refcounts the
246    * parents while running */
247   g_object_set (G_OBJECT (src), "silent", TRUE, NULL);
248   gst_bin_add (GST_BIN (pipeline), src);
249
250   sink = gst_element_factory_make ("fakesink", NULL);
251   /* need to silence the element as the deep_notify refcounts the
252    * parents while running */
253   g_object_set (G_OBJECT (sink), "silent", TRUE, NULL);
254   fail_if (sink == NULL, "Could not create fakesink");
255   gst_bin_add (GST_BIN (pipeline), sink);
256
257   fail_unless (gst_element_link (src, sink), "could not link src and sink");
258
259   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
260   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
261   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
262
263   bus = gst_pipeline_get_bus (pipeline);
264
265   /* change state to READY, spawning three messages */
266   GST_DEBUG ("setting pipeline to READY");
267   ret = gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_READY);
268   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
269
270   /* each object is referenced by a message */
271   ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
272   ASSERT_OBJECT_REFCOUNT (src, "src", 2);
273   ASSERT_OBJECT_REFCOUNT (sink, "sink", 2);
274   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 2);
275
276   pop_messages (bus, 3);
277   fail_if (gst_bus_have_pending (bus), "unexpected pending messages");
278
279   ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
280   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
281   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
282   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
283
284   /* change state to PAUSED, spawning three messages */
285   GST_DEBUG ("setting pipeline to PAUSED");
286   ret = gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PAUSED);
287   fail_unless (ret == GST_STATE_CHANGE_ASYNC);
288   ret =
289       gst_element_get_state (GST_ELEMENT (pipeline), &current, &pending,
290       GST_CLOCK_TIME_NONE);
291   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
292   fail_unless (current == GST_STATE_PAUSED);
293   fail_unless (pending == GST_STATE_VOID_PENDING);
294
295   /* wait for async thread to settle down */
296   GST_DEBUG ("waiting for refcount");
297   while (GST_OBJECT_REFCOUNT_VALUE (pipeline) > 3)
298     THREAD_SWITCH ();
299   GST_DEBUG ("refcount <= 3 now");
300
301   /* each object is referenced by a message;
302    * base_src is blocked in the push and has an extra refcount.
303    * base_sink_chain has taken a refcount on the sink, and is blocked on
304    * preroll
305    * The stream-status messages holds 2 more refs to the element */
306   ASSERT_OBJECT_REFCOUNT (src, "src", 4);
307   /* refcount can be 4 if the bin is still processing the async_done message of
308    * the sink. */
309   ASSERT_OBJECT_REFCOUNT_BETWEEN (sink, "sink", 2, 3);
310   /* 2 or 3 is valid, because the pipeline might still be posting 
311    * its state_change message */
312   ASSERT_OBJECT_REFCOUNT_BETWEEN (pipeline, "pipeline", 2, 3);
313
314   pop_messages (bus, 3);
315   pop_async_done (bus);
316   fail_if ((gst_bus_pop (bus)) != NULL);
317
318   ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
319   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
320   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
321   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
322
323   /* change state to PLAYING, spawning three messages */
324   GST_DEBUG ("setting pipeline to PLAYING");
325   ret = gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
326   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
327   ret =
328       gst_element_get_state (GST_ELEMENT (pipeline), &current, &pending,
329       GST_CLOCK_TIME_NONE);
330   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
331   fail_unless (current == GST_STATE_PLAYING);
332   fail_unless (pending == GST_STATE_VOID_PENDING);
333
334   /* each object is referenced by one message
335    * src might have an extra reference if it's still pushing
336    * sink might have an extra reference if it's still blocked on preroll
337    * pipeline posted a new-clock message too. */
338   ASSERT_OBJECT_REFCOUNT_BETWEEN (src, "src", 2, 3);
339   ASSERT_OBJECT_REFCOUNT_BETWEEN (sink, "sink", 2, 3);
340   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 3);
341
342   pop_messages (bus, 3);
343   fail_if ((gst_bus_pop (bus)) != NULL);
344
345   ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
346   /* src might have an extra reference if it's still pushing */
347   ASSERT_OBJECT_REFCOUNT_BETWEEN (src, "src", 1, 2);
348   /* sink might have an extra reference if it's still blocked on preroll */
349   ASSERT_OBJECT_REFCOUNT_BETWEEN (sink, "sink", 1, 2);
350   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
351
352   /* go back to READY, spawning six messages */
353   GST_DEBUG ("setting pipeline to READY");
354   ret = gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_READY);
355   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
356
357   /* each object is referenced by two messages, the source also has the
358    * stream-status message referencing it */
359   ASSERT_OBJECT_REFCOUNT (src, "src", 4);
360   ASSERT_OBJECT_REFCOUNT (sink, "sink", 3);
361   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 3);
362
363   pop_messages (bus, 6);
364   fail_if ((gst_bus_pop (bus)) != NULL);
365
366   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
367   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
368   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
369
370   /* setting pipeline to NULL flushes the bus automatically */
371   ret = gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
372   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
373
374   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
375   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
376   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
377
378   /* clean up */
379   gst_object_unref (bus);
380   gst_object_unref (pipeline);
381 }
382
383 GST_END_TEST;
384
385 GST_START_TEST (test_watch_for_state_change)
386 {
387   GstElement *src, *sink, *bin;
388   GstBus *bus;
389   GstStateChangeReturn ret;
390
391   bin = gst_element_factory_make ("bin", NULL);
392   fail_unless (bin != NULL, "Could not create bin");
393
394   bus = g_object_new (gst_bus_get_type (), NULL);
395   gst_element_set_bus (GST_ELEMENT_CAST (bin), bus);
396
397   src = gst_element_factory_make ("fakesrc", NULL);
398   fail_if (src == NULL, "Could not create fakesrc");
399   sink = gst_element_factory_make ("fakesink", NULL);
400   fail_if (sink == NULL, "Could not create fakesink");
401
402   gst_bin_add (GST_BIN (bin), sink);
403   gst_bin_add (GST_BIN (bin), src);
404
405   fail_unless (gst_element_link (src, sink), "could not link src and sink");
406
407   /* change state, spawning two times three messages */
408   ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED);
409   fail_unless (ret == GST_STATE_CHANGE_ASYNC);
410   ret =
411       gst_element_get_state (GST_ELEMENT (bin), NULL, NULL,
412       GST_CLOCK_TIME_NONE);
413   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
414
415   pop_messages (bus, 6);
416   pop_async_done (bus);
417
418   fail_unless (gst_bus_have_pending (bus) == FALSE,
419       "Unexpected messages on bus");
420
421   ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PLAYING);
422   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
423
424   pop_messages (bus, 3);
425
426   /* this one might return either SUCCESS or ASYNC, likely SUCCESS */
427   ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED);
428   gst_element_get_state (GST_ELEMENT (bin), NULL, NULL, GST_CLOCK_TIME_NONE);
429
430   pop_messages (bus, 3);
431   if (ret == GST_STATE_CHANGE_ASYNC)
432     pop_async_done (bus);
433
434   fail_unless (gst_bus_have_pending (bus) == FALSE,
435       "Unexpected messages on bus");
436
437   /* setting bin to NULL flushes the bus automatically */
438   ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL);
439   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
440
441   /* clean up */
442   gst_object_unref (bus);
443   gst_object_unref (bin);
444 }
445
446 GST_END_TEST;
447
448 GST_START_TEST (test_state_change_error_message)
449 {
450   GstElement *src, *sink, *bin;
451   GstBus *bus;
452   GstStateChangeReturn ret;
453
454   bin = gst_element_factory_make ("bin", NULL);
455   fail_unless (bin != NULL, "Could not create bin");
456
457   bus = g_object_new (gst_bus_get_type (), NULL);
458   gst_element_set_bus (GST_ELEMENT_CAST (bin), bus);
459
460   src = gst_element_factory_make ("fakesrc", NULL);
461   fail_if (src == NULL, "Could not create fakesrc");
462   sink = gst_element_factory_make ("fakesink", NULL);
463   fail_if (sink == NULL, "Could not create fakesink");
464
465   /* add but don't link elements */
466   gst_bin_add (GST_BIN (bin), sink);
467   gst_bin_add (GST_BIN (bin), src);
468
469   /* change state, this should succeed */
470   ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED);
471   fail_unless (ret == GST_STATE_CHANGE_ASYNC);
472
473   /* now wait, the streaming thread will error because the source is not
474    * linked. */
475   ret = gst_element_get_state (GST_ELEMENT (bin), NULL, NULL,
476       GST_CLOCK_TIME_NONE);
477   fail_unless (ret == GST_STATE_CHANGE_FAILURE);
478
479   gst_bus_set_flushing (bus, TRUE);
480
481   /* setting bin to NULL flushes the bus automatically */
482   ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL);
483   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
484
485   /* clean up */
486   gst_object_unref (bus);
487   gst_object_unref (bin);
488 }
489
490 GST_END_TEST;
491
492
493 /* adding an element with linked pads to a bin unlinks the
494  * pads */
495 GST_START_TEST (test_add_linked)
496 {
497   GstElement *src, *sink;
498   GstPad *srcpad, *sinkpad;
499   GstElement *pipeline;
500
501   pipeline = gst_pipeline_new (NULL);
502   fail_unless (pipeline != NULL, "Could not create pipeline");
503
504   src = gst_element_factory_make ("fakesrc", NULL);
505   fail_if (src == NULL, "Could not create fakesrc");
506   sink = gst_element_factory_make ("fakesink", NULL);
507   fail_if (sink == NULL, "Could not create fakesink");
508
509   srcpad = gst_element_get_static_pad (src, "src");
510   fail_unless (srcpad != NULL);
511   sinkpad = gst_element_get_static_pad (sink, "sink");
512   fail_unless (sinkpad != NULL);
513
514   fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK);
515
516   /* pads are linked now */
517   fail_unless (gst_pad_is_linked (srcpad));
518   fail_unless (gst_pad_is_linked (sinkpad));
519
520   /* adding element to bin voids hierarchy so pads are unlinked */
521   gst_bin_add (GST_BIN (pipeline), src);
522
523   /* check if pads really are unlinked */
524   fail_unless (!gst_pad_is_linked (srcpad));
525   fail_unless (!gst_pad_is_linked (sinkpad));
526
527   /* cannot link pads in wrong hierarchy */
528   fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_WRONG_HIERARCHY);
529
530   /* adding other element to bin as well */
531   gst_bin_add (GST_BIN (pipeline), sink);
532
533   /* now we can link again */
534   fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK);
535
536   /* check if pads really are linked */
537   fail_unless (gst_pad_is_linked (srcpad));
538   fail_unless (gst_pad_is_linked (sinkpad));
539
540   gst_object_unref (srcpad);
541   gst_object_unref (sinkpad);
542   gst_object_unref (pipeline);
543 }
544
545 GST_END_TEST;
546
547 /* adding ourself should fail */
548 GST_START_TEST (test_add_self)
549 {
550   GstElement *bin;
551
552   bin = gst_bin_new (NULL);
553   fail_unless (bin != NULL, "Could not create bin");
554
555   ASSERT_WARNING (gst_bin_add (GST_BIN (bin), bin));
556
557   gst_object_unref (bin);
558 }
559
560 GST_END_TEST;
561
562
563 /* g_print ("%10s: %4d => %4d\n", GST_OBJECT_NAME (msg->src), old, new); */
564
565 #define ASSERT_STATE_CHANGE_MSG(bus,element,old_state,new_state,num)          \
566   {                                                                           \
567     GstMessage *msg;                                                          \
568     GstState old = 0, new = 0, pending = 0;                                   \
569     msg = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, GST_SECOND);          \
570     fail_if (msg == NULL, "No state change message within 1 second (#"        \
571         G_STRINGIFY (num) ")");                                               \
572     gst_message_parse_state_changed (msg, &old, &new, &pending);              \
573     fail_if (msg->src != GST_OBJECT (element), G_STRINGIFY(element)           \
574         " should have changed state next (#" G_STRINGIFY (num) ")");          \
575     fail_if (old != old_state || new != new_state, "state change is not "     \
576         G_STRINGIFY (old_state) " => " G_STRINGIFY (new_state));              \
577     gst_message_unref (msg);                                                  \
578   }
579
580 GST_START_TEST (test_children_state_change_order_flagged_sink)
581 {
582   GstElement *src, *identity, *sink, *pipeline;
583   GstStateChangeReturn ret;
584   GstState current, pending;
585   GstBus *bus;
586
587   pipeline = gst_pipeline_new (NULL);
588   fail_unless (pipeline != NULL, "Could not create pipeline");
589
590   bus = gst_element_get_bus (pipeline);
591   fail_unless (bus != NULL, "Pipeline has no bus?!");
592
593   src = gst_element_factory_make ("fakesrc", NULL);
594   fail_if (src == NULL, "Could not create fakesrc");
595   g_object_set (src, "num-buffers", 5, NULL);
596
597   identity = gst_element_factory_make ("identity", NULL);
598   fail_if (identity == NULL, "Could not create identity");
599
600   sink = gst_element_factory_make ("fakesink", NULL);
601   fail_if (sink == NULL, "Could not create fakesink");
602
603   gst_bin_add_many (GST_BIN (pipeline), src, identity, sink, NULL);
604
605   fail_unless (gst_element_link (src, identity) == TRUE);
606   fail_unless (gst_element_link (identity, sink) == TRUE);
607
608   /* (1) Test state change with fakesink being a regular sink */
609   ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
610   fail_if (ret != GST_STATE_CHANGE_ASYNC,
611       "State change to PLAYING did not return ASYNC");
612   ret =
613       gst_element_get_state (pipeline, &current, &pending, GST_CLOCK_TIME_NONE);
614   fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to PLAYING failed");
615   fail_if (current != GST_STATE_PLAYING, "State change to PLAYING failed");
616   fail_if (pending != GST_STATE_VOID_PENDING, "State change to PLAYING failed");
617
618   /* NULL => READY */
619   ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_NULL, GST_STATE_READY, 101);
620   ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_NULL, GST_STATE_READY, 102);
621   ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_NULL, GST_STATE_READY, 103);
622   ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_NULL, GST_STATE_READY, 104);
623
624   /* READY => PAUSED */
625   /* because of pre-rolling, sink will return ASYNC on state
626    * change and change state later when it has a buffer */
627   GST_DEBUG ("popping READY -> PAUSED messages");
628   ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_READY, GST_STATE_PAUSED,
629       105);
630 #if 0
631   /* From here on, all bets are off. Usually the source changes state next,
632    * but it might just as well be that the first buffer produced by the
633    * source reaches the sink before the source has finished its state change,
634    * in which case the sink will commit its new state before the source ...  */
635   ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_READY, GST_STATE_PAUSED, 106);
636   ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_READY, GST_STATE_PAUSED, 107);
637 #else
638
639   pop_messages (bus, 2);        /* pop remaining ready => paused messages off the bus */
640   ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_READY, GST_STATE_PAUSED,
641       108);
642   pop_async_done (bus);
643 #endif
644   /* PAUSED => PLAYING */
645   GST_DEBUG ("popping PAUSED -> PLAYING messages");
646   ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_PAUSED, GST_STATE_PLAYING, 109);
647   ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_PAUSED, GST_STATE_PLAYING,
648       110);
649   ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_PAUSED, GST_STATE_PLAYING, 111);
650   ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_PAUSED, GST_STATE_PLAYING,
651       112);
652
653   /* don't set to NULL that will set the bus flushing and kill our messages */
654   ret = gst_element_set_state (pipeline, GST_STATE_READY);
655   fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to READY failed");
656   ret = gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
657   fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to READY failed");
658
659   /* TODO: do we need to check downwards state change order as well? */
660   pop_messages (bus, 4);        /* pop playing => paused messages off the bus */
661   pop_messages (bus, 4);        /* pop paused => ready messages off the bus */
662
663   while (GST_OBJECT_REFCOUNT_VALUE (pipeline) > 1)
664     THREAD_SWITCH ();
665
666   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
667   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
668   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
669
670   ret = gst_element_set_state (pipeline, GST_STATE_NULL);
671   fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to NULL failed");
672
673   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
674   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
675   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
676
677   gst_object_unref (bus);
678   gst_object_unref (pipeline);
679 }
680
681 GST_END_TEST;
682
683
684 GST_START_TEST (test_children_state_change_order_semi_sink)
685 {
686   GstElement *src, *identity, *sink, *pipeline;
687   GstStateChangeReturn ret;
688   GstState current, pending;
689   GstBus *bus;
690
691   /* (2) Now again, but check other code path where we don't have
692    *     a proper sink correctly flagged as such, but a 'semi-sink' */
693   pipeline = gst_pipeline_new (NULL);
694   fail_unless (pipeline != NULL, "Could not create pipeline");
695
696   bus = gst_element_get_bus (pipeline);
697   fail_unless (bus != NULL, "Pipeline has no bus?!");
698
699   src = gst_element_factory_make ("fakesrc", NULL);
700   fail_if (src == NULL, "Could not create fakesrc");
701
702   identity = gst_element_factory_make ("identity", NULL);
703   fail_if (identity == NULL, "Could not create identity");
704
705   sink = gst_element_factory_make ("fakesink", NULL);
706   fail_if (sink == NULL, "Could not create fakesink");
707
708   gst_bin_add_many (GST_BIN (pipeline), src, identity, sink, NULL);
709
710   fail_unless (gst_element_link (src, identity) == TRUE);
711   fail_unless (gst_element_link (identity, sink) == TRUE);
712
713   /* this is not very nice but should work just fine in this case. */
714   GST_OBJECT_FLAG_UNSET (sink, GST_ELEMENT_FLAG_SINK);  /* <======== */
715
716   ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
717   fail_if (ret != GST_STATE_CHANGE_ASYNC, "State change to PLAYING not ASYNC");
718   ret =
719       gst_element_get_state (pipeline, &current, &pending, GST_CLOCK_TIME_NONE);
720   fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to PLAYING failed");
721   fail_if (current != GST_STATE_PLAYING, "State change to PLAYING failed");
722   fail_if (pending != GST_STATE_VOID_PENDING, "State change to PLAYING failed");
723
724   /* NULL => READY */
725   ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_NULL, GST_STATE_READY, 201);
726   ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_NULL, GST_STATE_READY, 202);
727   ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_NULL, GST_STATE_READY, 203);
728   ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_NULL, GST_STATE_READY, 204);
729
730   /* READY => PAUSED */
731   /* because of pre-rolling, sink will return ASYNC on state
732    * change and change state later when it has a buffer */
733   GST_DEBUG ("popping READY -> PAUSED messages");
734   ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_READY, GST_STATE_PAUSED,
735       205);
736 #if 0
737   /* From here on, all bets are off. Usually the source changes state next,
738    * but it might just as well be that the first buffer produced by the
739    * source reaches the sink before the source has finished its state change,
740    * in which case the sink will commit its new state before the source ...  */
741   ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_READY, GST_STATE_PAUSED, 206);
742   ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_READY, GST_STATE_PAUSED, 207);
743 #else
744   pop_messages (bus, 2);        /* pop remaining ready => paused messages off the bus */
745   ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_READY, GST_STATE_PAUSED,
746       208);
747   pop_async_done (bus);
748
749   /* PAUSED => PLAYING */
750   GST_DEBUG ("popping PAUSED -> PLAYING messages");
751   ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_PAUSED, GST_STATE_PLAYING, 209);
752   ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_PAUSED, GST_STATE_PLAYING,
753       210);
754   ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_PAUSED, GST_STATE_PLAYING, 211);
755   ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_PAUSED, GST_STATE_PLAYING,
756       212);
757 #endif
758
759   /* don't set to NULL that will set the bus flushing and kill our messages */
760   ret = gst_element_set_state (pipeline, GST_STATE_READY);
761   fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to READY failed");
762
763   /* TODO: do we need to check downwards state change order as well? */
764   pop_messages (bus, 4);        /* pop playing => paused messages off the bus */
765   pop_messages (bus, 4);        /* pop paused => ready messages off the bus */
766
767   GST_DEBUG ("waiting for pipeline to reach refcount 1");
768   while (GST_OBJECT_REFCOUNT_VALUE (pipeline) > 1)
769     THREAD_SWITCH ();
770
771   GST_DEBUG ("checking refcount");
772   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
773   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
774   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
775
776   ret = gst_element_set_state (pipeline, GST_STATE_NULL);
777   fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to NULL failed");
778
779   GST_DEBUG ("checking refcount");
780   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
781   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
782   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
783
784   GST_DEBUG ("cleanup");
785   gst_object_unref (bus);
786   gst_object_unref (pipeline);
787 }
788
789 GST_END_TEST;
790
791 GST_START_TEST (test_children_state_change_order_two_sink)
792 {
793   GstElement *src, *tee, *identity, *sink1, *sink2, *pipeline;
794   GstStateChangeReturn ret;
795   GstBus *bus;
796
797   pipeline = gst_pipeline_new (NULL);
798   fail_unless (pipeline != NULL, "Could not create pipeline");
799
800   bus = gst_element_get_bus (pipeline);
801   fail_unless (bus != NULL, "Pipeline has no bus?!");
802
803   src = gst_element_factory_make ("fakesrc", NULL);
804   fail_if (src == NULL, "Could not create fakesrc");
805
806   tee = gst_element_factory_make ("tee", NULL);
807   fail_if (tee == NULL, "Could not create tee");
808
809   identity = gst_element_factory_make ("identity", NULL);
810   fail_if (identity == NULL, "Could not create identity");
811
812   sink1 = gst_element_factory_make ("fakesink", NULL);
813   fail_if (sink1 == NULL, "Could not create fakesink1");
814
815   sink2 = gst_element_factory_make ("fakesink", NULL);
816   fail_if (sink2 == NULL, "Could not create fakesink2");
817
818   gst_bin_add_many (GST_BIN (pipeline), src, tee, identity, sink1, sink2, NULL);
819
820   fail_unless (gst_element_link (src, tee) == TRUE);
821   fail_unless (gst_element_link (tee, identity) == TRUE);
822   fail_unless (gst_element_link (identity, sink1) == TRUE);
823   fail_unless (gst_element_link (tee, sink2) == TRUE);
824
825   ret = gst_element_set_state (pipeline, GST_STATE_READY);
826   fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to READY failed");
827
828   /* NULL => READY */
829   {
830     GstMessage *msg;
831     GstState old = 0, new = 0, pending = 0;
832     GstObject *first, *second;
833
834     msg = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, GST_SECOND);
835     fail_if (msg == NULL, "No state change message within 1 second (#201)");
836
837     gst_message_parse_state_changed (msg, &old, &new, &pending);
838     first = gst_object_ref (msg->src);
839
840     fail_if (first != GST_OBJECT (sink1) && first != GST_OBJECT (sink2),
841         "sink1 or sink2 should have changed state next #(202)");
842     gst_message_unref (msg);
843
844     msg = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, GST_SECOND);
845     fail_if (msg == NULL, "No state change message within 1 second (#201)");
846
847     gst_message_parse_state_changed (msg, &old, &new, &pending);
848     second = gst_object_ref (msg->src);
849
850     fail_if (second != GST_OBJECT (sink1) && second != GST_OBJECT (sink2),
851         "sink1 or sink2 should have changed state next #(202)");
852     gst_message_unref (msg);
853
854     fail_if (second == first, "got state change from same object");
855
856     gst_object_unref (first);
857     gst_object_unref (second);
858   }
859   ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_NULL, GST_STATE_READY, 203);
860   ASSERT_STATE_CHANGE_MSG (bus, tee, GST_STATE_NULL, GST_STATE_READY, 204);
861   ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_NULL, GST_STATE_READY, 205);
862   ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_NULL, GST_STATE_READY, 206);
863
864   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
865   ASSERT_OBJECT_REFCOUNT (tee, "tee", 1);
866   ASSERT_OBJECT_REFCOUNT (identity, "identity", 1);
867   ASSERT_OBJECT_REFCOUNT (sink1, "sink1", 1);
868   ASSERT_OBJECT_REFCOUNT (sink2, "sink2", 1);
869   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
870
871   ret = gst_element_set_state (pipeline, GST_STATE_NULL);
872   fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to NULL failed");
873
874   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
875   ASSERT_OBJECT_REFCOUNT (tee, "tee", 1);
876   ASSERT_OBJECT_REFCOUNT (identity, "identity", 1);
877   ASSERT_OBJECT_REFCOUNT (sink1, "sink1", 1);
878   ASSERT_OBJECT_REFCOUNT (sink2, "sink2", 1);
879   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
880
881   gst_object_unref (bus);
882   gst_object_unref (pipeline);
883 }
884
885 GST_END_TEST;
886
887 GST_START_TEST (test_iterate_sorted)
888 {
889   GstElement *src, *tee, *identity, *sink1, *sink2, *pipeline, *bin;
890   GstIterator *it;
891   GValue elem = { 0, };
892
893   pipeline = gst_pipeline_new (NULL);
894   fail_unless (pipeline != NULL, "Could not create pipeline");
895
896   bin = gst_bin_new (NULL);
897   fail_unless (bin != NULL, "Could not create bin");
898
899   src = gst_element_factory_make ("fakesrc", NULL);
900   fail_if (src == NULL, "Could not create fakesrc");
901
902   tee = gst_element_factory_make ("tee", NULL);
903   fail_if (tee == NULL, "Could not create tee");
904
905   sink1 = gst_element_factory_make ("fakesink", NULL);
906   fail_if (sink1 == NULL, "Could not create fakesink1");
907
908   gst_bin_add_many (GST_BIN (bin), src, tee, sink1, NULL);
909
910   fail_unless (gst_element_link (src, tee) == TRUE);
911   fail_unless (gst_element_link (tee, sink1) == TRUE);
912
913   identity = gst_element_factory_make ("identity", NULL);
914   fail_if (identity == NULL, "Could not create identity");
915
916   sink2 = gst_element_factory_make ("fakesink", NULL);
917   fail_if (sink2 == NULL, "Could not create fakesink2");
918
919   gst_bin_add_many (GST_BIN (pipeline), bin, identity, sink2, NULL);
920
921   fail_unless (gst_element_link (tee, identity) == TRUE);
922   fail_unless (gst_element_link (identity, sink2) == TRUE);
923
924   it = gst_bin_iterate_sorted (GST_BIN (pipeline));
925   fail_unless (gst_iterator_next (it, &elem) == GST_ITERATOR_OK);
926   fail_unless (g_value_get_object (&elem) == (gpointer) sink2);
927   g_value_reset (&elem);
928
929   fail_unless (gst_iterator_next (it, &elem) == GST_ITERATOR_OK);
930   fail_unless (g_value_get_object (&elem) == (gpointer) identity);
931   g_value_reset (&elem);
932
933   fail_unless (gst_iterator_next (it, &elem) == GST_ITERATOR_OK);
934   fail_unless (g_value_get_object (&elem) == (gpointer) bin);
935   g_value_reset (&elem);
936
937   g_value_unset (&elem);
938   gst_iterator_free (it);
939
940   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
941   gst_object_unref (pipeline);
942 }
943
944 GST_END_TEST;
945
946 static void
947 test_link_structure_change_state_changed_sync_cb (GstBus * bus,
948     GstMessage * message, gpointer data)
949 {
950   GstPipeline *pipeline = GST_PIPELINE (data);
951   GstElement *src, *identity, *sink;
952   GstState old, snew, pending;
953
954   sink = gst_bin_get_by_name (GST_BIN (pipeline), "sink");
955   fail_unless (sink != NULL, "Could not get sink");
956
957   gst_message_parse_state_changed (message, &old, &snew, &pending);
958   if (message->src != GST_OBJECT (sink) || snew != GST_STATE_READY) {
959     gst_object_unref (sink);
960     return;
961   }
962
963   src = gst_bin_get_by_name (GST_BIN (pipeline), "src");
964   fail_unless (src != NULL, "Could not get src");
965
966   identity = gst_bin_get_by_name (GST_BIN (pipeline), "identity");
967   fail_unless (identity != NULL, "Could not get identity");
968
969   /* link src to identity, the pipeline should detect the new link and
970    * resync the state change */
971   fail_unless (gst_element_link (src, identity) == TRUE);
972
973   gst_object_unref (src);
974   gst_object_unref (identity);
975   gst_object_unref (sink);
976 }
977
978 GST_START_TEST (test_link_structure_change)
979 {
980   GstElement *src, *identity, *sink, *pipeline;
981   GstBus *bus;
982   GstState state;
983
984   pipeline = gst_pipeline_new (NULL);
985   fail_unless (pipeline != NULL, "Could not create pipeline");
986
987   bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
988   fail_unless (bus != NULL, "Could not get bus");
989
990   /* use the sync signal handler to link elements while the pipeline is still
991    * doing the state change */
992   gst_bus_set_sync_handler (bus, gst_bus_sync_signal_handler, pipeline);
993   g_object_connect (bus, "signal::sync-message::state-changed",
994       G_CALLBACK (test_link_structure_change_state_changed_sync_cb), pipeline,
995       NULL);
996
997   src = gst_element_factory_make ("fakesrc", "src");
998   fail_if (src == NULL, "Could not create fakesrc");
999
1000   identity = gst_element_factory_make ("identity", "identity");
1001   fail_if (identity == NULL, "Could not create identity");
1002
1003   sink = gst_element_factory_make ("fakesink", "sink");
1004   fail_if (sink == NULL, "Could not create fakesink1");
1005
1006   gst_bin_add_many (GST_BIN (pipeline), src, identity, sink, NULL);
1007
1008   gst_element_set_state (pipeline, GST_STATE_READY);
1009   gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
1010
1011   /* the state change will be done on src only if the pipeline correctly resyncs
1012    * after that fakesrc has been linked to identity */
1013   gst_element_get_state (src, &state, NULL, 0);
1014   fail_unless_equals_int (state, GST_STATE_READY);
1015
1016   /* clean up */
1017   gst_element_set_state (pipeline, GST_STATE_NULL);
1018   gst_object_unref (bus);
1019   gst_object_unref (pipeline);
1020 }
1021
1022 GST_END_TEST;
1023
1024 static GstBusSyncReply
1025 sync_handler_remove_sink (GstBus * bus, GstMessage * message, gpointer data)
1026 {
1027   if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ERROR) {
1028     GstElement *child;
1029
1030     child = gst_bin_get_by_name (GST_BIN (data), "fakesink");
1031     fail_unless (child != NULL, "Could not find fakesink");
1032
1033     gst_bin_remove (GST_BIN (data), child);
1034     gst_object_unref (child);
1035   }
1036   return GST_BUS_PASS;
1037 }
1038
1039 GST_START_TEST (test_state_failure_remove)
1040 {
1041   GstElement *src, *sink, *pipeline;
1042   GstBus *bus;
1043   GstStateChangeReturn ret;
1044
1045   pipeline = gst_pipeline_new (NULL);
1046   fail_unless (pipeline != NULL, "Could not create pipeline");
1047
1048   src = gst_element_factory_make ("fakesrc", "fakesrc");
1049   fail_unless (src != NULL, "Could not create fakesrc");
1050
1051   sink = gst_element_factory_make ("fakesink", "fakesink");
1052   fail_unless (sink != NULL, "Could not create fakesink");
1053
1054   g_object_set (sink, "state-error", 1, NULL);
1055
1056   gst_bin_add (GST_BIN (pipeline), src);
1057   gst_bin_add (GST_BIN (pipeline), sink);
1058
1059   gst_element_link (src, sink);
1060
1061   bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
1062   fail_unless (bus != NULL, "Could not get bus");
1063
1064   gst_bus_set_sync_handler (bus, sync_handler_remove_sink, pipeline);
1065
1066   ret = gst_element_set_state (pipeline, GST_STATE_READY);
1067   fail_unless (ret == GST_STATE_CHANGE_SUCCESS,
1068       "did not get state change success");
1069
1070   gst_element_set_state (pipeline, GST_STATE_NULL);
1071
1072   gst_object_unref (bus);
1073   gst_object_unref (pipeline);
1074 }
1075
1076 GST_END_TEST;
1077
1078 GST_START_TEST (test_many_bins)
1079 {
1080   GstStateChangeReturn ret;
1081   GstElement *src, *sink, *pipeline, *last_bin = NULL;
1082   gint i;
1083
1084 #define NUM_BINS 2000
1085
1086   pipeline = gst_pipeline_new (NULL);
1087   fail_unless (pipeline != NULL, "Could not create pipeline");
1088
1089   src = gst_element_factory_make ("fakesrc", "fakesrc");
1090   fail_unless (src != NULL, "Could not create fakesrc");
1091   g_object_set (src, "num-buffers", 3, NULL);
1092
1093   sink = gst_element_factory_make ("fakesink", "fakesink");
1094   fail_unless (sink != NULL, "Could not create fakesink");
1095
1096   gst_bin_add (GST_BIN (pipeline), src);
1097   gst_bin_add (GST_BIN (pipeline), sink);
1098
1099   for (i = 0; i < NUM_BINS; ++i) {
1100     GstElement *bin, *identity;
1101     GstPad *srcpad, *sinkpad;
1102
1103     bin = gst_bin_new (NULL);
1104     fail_unless (bin != NULL, "Could not create bin %d", i);
1105     identity = gst_element_factory_make ("identity", "identity");
1106     fail_unless (identity != NULL, "Could not create identity %d", i);
1107     g_object_set (identity, "silent", TRUE, NULL);
1108     gst_bin_add (GST_BIN (bin), identity);
1109     sinkpad = gst_element_get_static_pad (identity, "sink");
1110     srcpad = gst_element_get_static_pad (identity, "src");
1111     gst_element_add_pad (bin, gst_ghost_pad_new ("sink", sinkpad));
1112     gst_element_add_pad (bin, gst_ghost_pad_new ("src", srcpad));
1113     gst_object_unref (sinkpad);
1114     gst_object_unref (srcpad);
1115
1116     gst_bin_add (GST_BIN (pipeline), bin);
1117
1118     if (last_bin == NULL) {
1119       srcpad = gst_element_get_static_pad (src, "src");
1120     } else {
1121       srcpad = gst_element_get_static_pad (last_bin, "src");
1122     }
1123     sinkpad = gst_element_get_static_pad (bin, "sink");
1124     gst_pad_link_full (srcpad, sinkpad, GST_PAD_LINK_CHECK_NOTHING);
1125     gst_object_unref (sinkpad);
1126     gst_object_unref (srcpad);
1127
1128
1129     last_bin = bin;
1130
1131     /* insert some queues to limit the number of function calls in a row */
1132     if ((i % 100) == 0) {
1133       GstElement *q = gst_element_factory_make ("queue", NULL);
1134
1135       GST_LOG ("bin #%d, inserting queue", i);
1136       gst_bin_add (GST_BIN (pipeline), q);
1137       fail_unless (gst_element_link (last_bin, q));
1138       last_bin = q;
1139     }
1140   }
1141
1142   fail_unless (gst_element_link (last_bin, sink));
1143
1144   ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
1145   fail_unless_equals_int (ret, GST_STATE_CHANGE_ASYNC);
1146
1147   for (i = 0; i < 15; ++i) {
1148     GST_INFO ("waiting for preroll ...");
1149     ret = gst_element_get_state (pipeline, NULL, NULL, GST_SECOND);
1150     if (ret != GST_STATE_CHANGE_ASYNC)
1151       break;
1152   }
1153   fail_unless_equals_int (ret, GST_STATE_CHANGE_SUCCESS);
1154
1155   gst_element_set_state (pipeline, GST_STATE_NULL);
1156   gst_object_unref (pipeline);
1157 }
1158
1159 GST_END_TEST;
1160
1161 static GstPadProbeReturn
1162 fakesrc_pad_blocked_cb (GstPad * pad, GstPadProbeInfo * info, void *arg)
1163 {
1164   GstPipeline *pipeline = (GstPipeline *) arg;
1165   GstElement *src, *sink;
1166
1167   src = gst_bin_get_by_name (GST_BIN (pipeline), "fakesrc");
1168   fail_unless (src != NULL, "Could not get fakesrc");
1169
1170   sink = gst_element_factory_make ("fakesink", "fakesink");
1171   fail_unless (sink != NULL, "Could not create fakesink");
1172
1173   g_object_set (sink, "state-error", 1, NULL);
1174   gst_bin_add (GST_BIN (pipeline), sink);
1175
1176   gst_element_link (src, sink);
1177   gst_element_sync_state_with_parent (sink);
1178   gst_object_unref (src);
1179
1180   return GST_PAD_PROBE_REMOVE;
1181 }
1182
1183 GST_START_TEST (test_state_failure_unref)
1184 {
1185   GstElement *src, *pipeline;
1186   GstPad *srcpad;
1187   GstBus *bus;
1188   GstStateChangeReturn ret;
1189   GstMessage *msg;
1190
1191   pipeline = gst_pipeline_new (NULL);
1192   fail_unless (pipeline != NULL, "Could not create pipeline");
1193
1194   src = gst_element_factory_make ("fakesrc", "fakesrc");
1195   fail_unless (src != NULL, "Could not create fakesrc");
1196
1197   srcpad = gst_element_get_static_pad (src, "src");
1198   fail_unless (srcpad != NULL, "Could not get fakesrc srcpad");
1199
1200   gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
1201       fakesrc_pad_blocked_cb, pipeline, NULL);
1202   gst_object_unref (srcpad);
1203
1204   gst_bin_add (GST_BIN (pipeline), src);
1205
1206   bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
1207   fail_unless (bus != NULL, "Could not get bus");
1208
1209   gst_element_set_state (pipeline, GST_STATE_PLAYING);
1210
1211   /* Wait for an error message from our fakesink (added from the
1212      pad block callback). */
1213   msg = gst_bus_poll (bus, GST_MESSAGE_ERROR, GST_SECOND);
1214   fail_if (msg == NULL, "No error message within 1 second");
1215   gst_message_unref (msg);
1216
1217   /* Check that after this failure, we can still stop, and then unref, the
1218      pipeline. This should always be possible. */
1219   ret = gst_element_set_state (pipeline, GST_STATE_NULL);
1220   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "downward state change failed");
1221
1222   gst_object_unref (bus);
1223   gst_object_unref (pipeline);
1224 }
1225
1226 GST_END_TEST;
1227
1228 static void
1229 on_sync_bus_error (GstBus * bus, GstMessage * msg)
1230 {
1231   fail_if (msg != NULL);
1232 }
1233
1234 GST_START_TEST (test_state_change_skip)
1235 {
1236   GstElement *sink, *pipeline;
1237   GstStateChangeReturn ret;
1238   GstBus *bus;
1239
1240   pipeline = gst_pipeline_new (NULL);
1241   fail_unless (pipeline != NULL, "Could not create pipeline");
1242
1243   bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
1244   fail_unless (bus != NULL, "Could not get bus");
1245
1246   /* no errors */
1247   gst_bus_enable_sync_message_emission (bus);
1248   g_signal_connect (bus, "sync-message::error", (GCallback) on_sync_bus_error,
1249       NULL);
1250
1251   sink = gst_element_factory_make ("fakesink", "fakesink");
1252   fail_unless (sink != NULL, "Could not create fakesink");
1253   gst_element_set_state (sink, GST_STATE_PAUSED);
1254
1255   g_object_set (sink, "state-error", 5, NULL);
1256
1257   gst_bin_add (GST_BIN (pipeline), sink);
1258   gst_element_set_state (pipeline, GST_STATE_PLAYING);
1259
1260   g_object_set (sink, "state-error", 0, NULL);
1261
1262   /* Check that after this failure, we can still stop, and then unref, the
1263      pipeline. This should always be possible. */
1264   ret = gst_element_set_state (pipeline, GST_STATE_NULL);
1265   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "downward state change failed");
1266
1267   gst_object_unref (pipeline);
1268 }
1269
1270 GST_END_TEST;
1271
1272 static Suite *
1273 gst_bin_suite (void)
1274 {
1275   Suite *s = suite_create ("GstBin");
1276   TCase *tc_chain = tcase_create ("bin tests");
1277
1278   tcase_set_timeout (tc_chain, 0);
1279
1280   suite_add_tcase (s, tc_chain);
1281   tcase_add_test (tc_chain, test_interface);
1282   tcase_add_test (tc_chain, test_children_state_change_order_flagged_sink);
1283   tcase_add_test (tc_chain, test_children_state_change_order_semi_sink);
1284   tcase_add_test (tc_chain, test_children_state_change_order_two_sink);
1285   tcase_add_test (tc_chain, test_message_state_changed);
1286   tcase_add_test (tc_chain, test_message_state_changed_child);
1287   tcase_add_test (tc_chain, test_message_state_changed_children);
1288   tcase_add_test (tc_chain, test_watch_for_state_change);
1289   tcase_add_test (tc_chain, test_state_change_error_message);
1290   tcase_add_test (tc_chain, test_add_linked);
1291   tcase_add_test (tc_chain, test_add_self);
1292   tcase_add_test (tc_chain, test_iterate_sorted);
1293   tcase_add_test (tc_chain, test_link_structure_change);
1294   tcase_add_test (tc_chain, test_state_failure_remove);
1295   tcase_add_test (tc_chain, test_state_failure_unref);
1296   tcase_add_test (tc_chain, test_state_change_skip);
1297
1298   /* fails on OSX build bot for some reason, and is a bit silly anyway */
1299   if (0)
1300     tcase_add_test (tc_chain, test_many_bins);
1301
1302   return s;
1303 }
1304
1305 GST_CHECK_MAIN (gst_bin);