tests: bin: add more tests for suppressed flags
[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., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 #include <gst/check/gstcheck.h>
24 #include <gst/base/gstbasesrc.h>
25
26 static void
27 pop_async_done (GstBus * bus)
28 {
29   GstMessage *message;
30
31   GST_DEBUG ("popping async-done message");
32   message = gst_bus_poll (bus, GST_MESSAGE_ASYNC_DONE, -1);
33
34   fail_unless (message && GST_MESSAGE_TYPE (message)
35       == GST_MESSAGE_ASYNC_DONE, "did not get GST_MESSAGE_ASYNC_DONE");
36
37   gst_message_unref (message);
38   GST_DEBUG ("popped message");
39 }
40
41 static void
42 pop_messages (GstBus * bus, int count)
43 {
44   GstMessage *message;
45
46   int i;
47
48   GST_DEBUG ("popping %d messages", count);
49   for (i = 0; i < count; ++i) {
50     message = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, -1);
51
52     fail_unless (message && GST_MESSAGE_TYPE (message)
53         == GST_MESSAGE_STATE_CHANGED, "did not get GST_MESSAGE_STATE_CHANGED");
54
55     gst_message_unref (message);
56   }
57   GST_DEBUG ("popped %d messages", count);
58 }
59
60 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
61     GST_PAD_SRC,
62     GST_PAD_ALWAYS,
63     GST_STATIC_CAPS_ANY);
64
65 static gpointer
66 push_one_eos (GstPad * pad)
67 {
68   GST_DEBUG_OBJECT (pad, "Pushing EOS event");
69   gst_pad_push_event (pad, gst_event_new_eos ());
70
71   return NULL;
72 }
73
74 static gpointer
75 push_one_stream_start (GstPad * pad)
76 {
77   GST_DEBUG_OBJECT (pad, "Pushing STREAM_START event");
78   gst_pad_push_event (pad, gst_event_new_stream_start ("test"));
79
80   return NULL;
81 }
82
83 GST_START_TEST (test_interface)
84 {
85   GstBin *bin, *bin2;
86   GstElement *filesrc;
87   GstIterator *it;
88   GValue item = { 0, };
89
90   bin = GST_BIN (gst_bin_new (NULL));
91   fail_unless (bin != NULL, "Could not create bin");
92
93   filesrc = gst_element_factory_make ("filesrc", NULL);
94   fail_unless (filesrc != NULL, "Could not create filesrc");
95   fail_unless (GST_IS_URI_HANDLER (filesrc), "Filesrc not a URI handler");
96   gst_bin_add (bin, filesrc);
97
98   fail_unless (gst_bin_get_by_interface (bin, GST_TYPE_URI_HANDLER) == filesrc);
99   gst_object_unref (filesrc);
100
101   it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER);
102   fail_unless (it != NULL);
103   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
104   fail_unless (g_value_get_object (&item) == (gpointer) filesrc);
105   g_value_reset (&item);
106   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
107   gst_iterator_free (it);
108
109   gst_bin_add_many (bin,
110       gst_element_factory_make ("identity", NULL),
111       gst_element_factory_make ("identity", NULL),
112       gst_element_factory_make ("identity", NULL), NULL);
113   it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER);
114   fail_unless (it != NULL);
115   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
116   fail_unless (g_value_get_object (&item) == (gpointer) filesrc);
117   g_value_reset (&item);
118   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
119   gst_iterator_free (it);
120
121   bin2 = bin;
122   bin = GST_BIN (gst_bin_new (NULL));
123   fail_unless (bin != NULL);
124   gst_bin_add_many (bin,
125       gst_element_factory_make ("identity", NULL),
126       gst_element_factory_make ("identity", NULL),
127       GST_ELEMENT (bin2), gst_element_factory_make ("identity", NULL), NULL);
128   it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER);
129   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
130   fail_unless (g_value_get_object (&item) == (gpointer) filesrc);
131   g_value_reset (&item);
132   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
133   gst_iterator_free (it);
134
135   gst_bin_add (bin, gst_element_factory_make ("filesrc", NULL));
136   gst_bin_add (bin2, gst_element_factory_make ("filesrc", NULL));
137   it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER);
138   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
139   g_value_reset (&item);
140   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
141   g_value_reset (&item);
142   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
143   g_value_reset (&item);
144   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
145   g_value_unset (&item);
146   gst_iterator_free (it);
147
148   gst_object_unref (bin);
149 }
150
151 GST_END_TEST;
152
153 GST_START_TEST (test_eos)
154 {
155   GstBus *bus;
156   GstElement *pipeline, *sink1, *sink2;
157   GstMessage *message;
158   GstPad *pad1, *pad2;
159   GThread *thread1, *thread2;
160
161   pipeline = gst_pipeline_new ("test_eos");
162   bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
163
164   sink1 = gst_element_factory_make ("fakesink", "sink1");
165   sink2 = gst_element_factory_make ("fakesink", "sink2");
166
167   gst_bin_add_many (GST_BIN (pipeline), sink1, sink2, NULL);
168
169   pad1 = gst_check_setup_src_pad_by_name (sink1, &srctemplate, "sink");
170   pad2 = gst_check_setup_src_pad_by_name (sink2, &srctemplate, "sink");
171
172   gst_pad_set_active (pad1, TRUE);
173   gst_pad_set_active (pad2, TRUE);
174
175   fail_if (gst_element_set_state (GST_ELEMENT (pipeline),
176           GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
177
178   /* Send one EOS to sink1 */
179   thread1 = g_thread_new ("thread1", (GThreadFunc) push_one_eos, pad1);
180
181   /* Make sure the EOS message is not sent */
182   message =
183       gst_bus_poll (bus, GST_MESSAGE_ERROR | GST_MESSAGE_EOS, 2 * GST_SECOND);
184   fail_if (message != NULL);
185
186   /* Send one EOS to sink2 */
187   thread2 = g_thread_new ("thread2", (GThreadFunc) push_one_eos, pad2);
188
189   /* Make sure the EOS message is sent then */
190   message = gst_bus_poll (bus, GST_MESSAGE_ERROR | GST_MESSAGE_EOS, -1);
191   fail_if (message == NULL);
192   fail_unless (GST_MESSAGE_TYPE (message) == GST_MESSAGE_EOS);
193   gst_message_unref (message);
194
195   /* Cleanup */
196   g_thread_join (thread1);
197   g_thread_join (thread2);
198
199   gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
200   gst_pad_set_active (pad1, FALSE);
201   gst_pad_set_active (pad2, FALSE);
202   gst_check_teardown_src_pad (sink1);
203   gst_check_teardown_src_pad (sink2);
204   gst_object_unref (bus);
205   gst_object_unref (pipeline);
206 }
207
208 GST_END_TEST;
209
210 GST_START_TEST (test_stream_start)
211 {
212   GstBus *bus;
213   GstElement *pipeline, *sink1, *sink2;
214   GstMessage *message;
215   GstPad *pad1, *pad2;
216   GThread *thread1, *thread2;
217
218   pipeline = gst_pipeline_new ("test_stream_start");
219   bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
220
221   sink1 = gst_element_factory_make ("fakesink", "sink1");
222   sink2 = gst_element_factory_make ("fakesink", "sink2");
223
224   gst_bin_add_many (GST_BIN (pipeline), sink1, sink2, NULL);
225
226   pad1 = gst_check_setup_src_pad_by_name (sink1, &srctemplate, "sink");
227   pad2 = gst_check_setup_src_pad_by_name (sink2, &srctemplate, "sink");
228
229   gst_pad_set_active (pad1, TRUE);
230   gst_pad_set_active (pad2, TRUE);
231
232   fail_if (gst_element_set_state (GST_ELEMENT (pipeline),
233           GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
234
235   /* Send one STREAM_START to sink1 */
236   thread1 = g_thread_new ("thread1", (GThreadFunc) push_one_stream_start, pad1);
237
238   /* Make sure the STREAM_START message is not sent */
239   message =
240       gst_bus_poll (bus, GST_MESSAGE_ERROR | GST_MESSAGE_STREAM_START,
241       2 * GST_SECOND);
242   fail_if (message != NULL);
243
244   /* Send one STREAM_START to sink2 */
245   thread2 = g_thread_new ("thread2", (GThreadFunc) push_one_stream_start, pad2);
246
247   /* Make sure the STREAM_START message is sent then */
248   message =
249       gst_bus_poll (bus, GST_MESSAGE_ERROR | GST_MESSAGE_STREAM_START, -1);
250   fail_if (message == NULL);
251   fail_unless (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STREAM_START);
252   gst_message_unref (message);
253
254   /* Cleanup */
255   g_thread_join (thread1);
256   g_thread_join (thread2);
257
258   gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
259   gst_pad_set_active (pad1, FALSE);
260   gst_pad_set_active (pad2, FALSE);
261   gst_check_teardown_src_pad (sink1);
262   gst_check_teardown_src_pad (sink2);
263   gst_object_unref (bus);
264   gst_object_unref (pipeline);
265 }
266
267 GST_END_TEST;
268
269 GST_START_TEST (test_message_state_changed)
270 {
271   GstBin *bin;
272   GstBus *bus;
273   GstMessage *message;
274   GstStateChangeReturn ret;
275
276   bin = GST_BIN (gst_bin_new (NULL));
277   fail_unless (bin != NULL, "Could not create bin");
278   ASSERT_OBJECT_REFCOUNT (bin, "bin", 1);
279
280   bus = g_object_new (gst_bus_get_type (), NULL);
281   gst_element_set_bus (GST_ELEMENT_CAST (bin), bus);
282
283   /* change state, spawning a message, causing an incref on the bin */
284   ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_READY);
285   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
286
287   ASSERT_OBJECT_REFCOUNT (bin, "bin", 2);
288
289   /* get and unref the message, causing a decref on the bin */
290   message = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, -1);
291
292   fail_unless (message && GST_MESSAGE_TYPE (message)
293       == GST_MESSAGE_STATE_CHANGED, "did not get GST_MESSAGE_STATE_CHANGED");
294
295   gst_message_unref (message);
296
297   ASSERT_OBJECT_REFCOUNT (bin, "bin", 1);
298
299   gst_bus_set_flushing (bus, TRUE);
300
301   /* clean up */
302   ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL);
303   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
304
305   gst_object_unref (bus);
306   gst_object_unref (bin);
307 }
308
309 GST_END_TEST;
310
311 GST_START_TEST (test_message_state_changed_child)
312 {
313   GstBin *bin;
314   GstElement *src;
315   GstBus *bus;
316   GstMessage *message;
317   GstStateChangeReturn ret;
318
319   bin = GST_BIN (gst_bin_new (NULL));
320   fail_unless (bin != NULL, "Could not create bin");
321   ASSERT_OBJECT_REFCOUNT (bin, "bin", 1);
322
323   bus = g_object_new (gst_bus_get_type (), NULL);
324   gst_element_set_bus (GST_ELEMENT_CAST (bin), bus);
325
326   src = gst_element_factory_make ("fakesrc", NULL);
327   fail_if (src == NULL, "Could not create fakesrc");
328   gst_bin_add (bin, src);
329   ASSERT_OBJECT_REFCOUNT (bin, "bin", 1);
330   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
331
332   /* change state, spawning two messages:
333    * - first for fakesrc, forwarded to bin's bus, causing incref on fakesrc
334    * - second for bin, causing an incref on the bin */
335   GST_DEBUG ("setting bin to READY");
336   ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_READY);
337   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
338
339   ASSERT_OBJECT_REFCOUNT (src, "src", 2);
340   ASSERT_OBJECT_REFCOUNT (bin, "bin", 2);
341
342   /* get and unref the message, causing a decref on the src */
343   message = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, -1);
344   fail_unless (message && GST_MESSAGE_TYPE (message)
345       == GST_MESSAGE_STATE_CHANGED, "did not get GST_MESSAGE_STATE_CHANGED");
346
347   fail_unless (message->src == GST_OBJECT (src));
348   gst_message_unref (message);
349
350   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
351   ASSERT_OBJECT_REFCOUNT (bin, "bin", 2);
352
353   /* get and unref message 2, causing a decref on the bin */
354   message = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, -1);
355   fail_unless (message && GST_MESSAGE_TYPE (message)
356       == GST_MESSAGE_STATE_CHANGED, "did not get GST_MESSAGE_STATE_CHANGED");
357
358   fail_unless (message->src == GST_OBJECT (bin));
359   gst_message_unref (message);
360
361   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
362   ASSERT_OBJECT_REFCOUNT (bin, "bin", 1);
363
364   gst_bus_set_flushing (bus, TRUE);
365
366   /* clean up */
367   ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL);
368   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
369
370   gst_object_unref (bus);
371   gst_object_unref (bin);
372 }
373
374 GST_END_TEST;
375
376 GST_START_TEST (test_message_state_changed_children)
377 {
378   GstPipeline *pipeline;
379   GstElement *src, *sink;
380   GstBus *bus;
381   GstStateChangeReturn ret;
382   GstState current, pending;
383
384   pipeline = GST_PIPELINE (gst_pipeline_new (NULL));
385   fail_unless (pipeline != NULL, "Could not create pipeline");
386   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
387
388   src = gst_element_factory_make ("fakesrc", NULL);
389   fail_if (src == NULL, "Could not create fakesrc");
390   /* need to silence the element as the deep_notify refcounts the
391    * parents while running */
392   g_object_set (G_OBJECT (src), "silent", TRUE, NULL);
393   gst_bin_add (GST_BIN (pipeline), src);
394
395   sink = gst_element_factory_make ("fakesink", NULL);
396   /* need to silence the element as the deep_notify refcounts the
397    * parents while running */
398   g_object_set (G_OBJECT (sink), "silent", TRUE, NULL);
399   fail_if (sink == NULL, "Could not create fakesink");
400   gst_bin_add (GST_BIN (pipeline), sink);
401
402   fail_unless (gst_element_link (src, sink), "could not link src and sink");
403
404   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
405   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
406   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
407
408   bus = gst_pipeline_get_bus (pipeline);
409
410   /* change state to READY, spawning three messages */
411   GST_DEBUG ("setting pipeline to READY");
412   ret = gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_READY);
413   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
414
415   /* each object is referenced by a message */
416   ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
417   ASSERT_OBJECT_REFCOUNT (src, "src", 2);
418   ASSERT_OBJECT_REFCOUNT (sink, "sink", 2);
419   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 2);
420
421   pop_messages (bus, 3);
422   fail_if (gst_bus_have_pending (bus), "unexpected pending messages");
423
424   ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
425   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
426   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
427   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
428
429   /* change state to PAUSED, spawning four messages */
430   /* STATE_CHANGED (NULL => READY)
431    * STREAM_START
432    * ASYNC_DONE
433    * STATE_CHANGED (READY => PAUSED)
434    */
435   GST_DEBUG ("setting pipeline to PAUSED");
436   ret = gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PAUSED);
437   fail_unless (ret == GST_STATE_CHANGE_ASYNC);
438   ret =
439       gst_element_get_state (GST_ELEMENT (pipeline), &current, &pending,
440       GST_CLOCK_TIME_NONE);
441   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
442   fail_unless (current == GST_STATE_PAUSED);
443   fail_unless (pending == GST_STATE_VOID_PENDING);
444
445   /* wait for async thread to settle down */
446   GST_DEBUG ("waiting for refcount");
447   while (GST_OBJECT_REFCOUNT_VALUE (pipeline) > 4)
448     THREAD_SWITCH ();
449   GST_DEBUG ("refcount <= 4 now");
450
451   /* each object is referenced by a message;
452    * base_src is blocked in the push and has an extra refcount.
453    * base_sink_chain has taken a refcount on the sink, and is blocked on
454    * preroll
455    * The stream-status messages holds 2 more refs to the element */
456   ASSERT_OBJECT_REFCOUNT (src, "src", 4);
457   /* refcount can be 4 if the bin is still processing the async_done message of
458    * the sink. */
459   ASSERT_OBJECT_REFCOUNT_BETWEEN (sink, "sink", 2, 3);
460   /* 3 or 4 is valid, because the pipeline might still be posting 
461    * its state_change message */
462   ASSERT_OBJECT_REFCOUNT_BETWEEN (pipeline, "pipeline", 3, 4);
463
464   pop_messages (bus, 3);
465   pop_async_done (bus);
466   fail_if ((gst_bus_pop (bus)) != NULL);
467
468   ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
469   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
470   ASSERT_OBJECT_REFCOUNT (sink, "sink", 2);
471   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
472
473   /* change state to PLAYING, spawning three messages */
474   GST_DEBUG ("setting pipeline to PLAYING");
475   ret = gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
476   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
477   ret =
478       gst_element_get_state (GST_ELEMENT (pipeline), &current, &pending,
479       GST_CLOCK_TIME_NONE);
480   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
481   fail_unless (current == GST_STATE_PLAYING);
482   fail_unless (pending == GST_STATE_VOID_PENDING);
483
484   /* each object is referenced by one message
485    * src might have an extra reference if it's still pushing
486    * sink might have an extra reference if it's still blocked on preroll
487    * pipeline posted a new-clock message too. */
488   ASSERT_OBJECT_REFCOUNT_BETWEEN (src, "src", 2, 3);
489   ASSERT_OBJECT_REFCOUNT_BETWEEN (sink, "sink", 2, 4);
490   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 3);
491
492   pop_messages (bus, 3);
493   fail_if ((gst_bus_pop (bus)) != NULL);
494
495   ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
496   /* src might have an extra reference if it's still pushing */
497   ASSERT_OBJECT_REFCOUNT_BETWEEN (src, "src", 1, 2);
498   /* sink might have an extra reference if it's still blocked on preroll */
499   ASSERT_OBJECT_REFCOUNT_BETWEEN (sink, "sink", 1, 3);
500   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
501
502   /* go back to READY, spawning six messages */
503   GST_DEBUG ("setting pipeline to READY");
504   ret = gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_READY);
505   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
506
507   /* each object is referenced by two messages, the source also has the
508    * stream-status message referencing it */
509   ASSERT_OBJECT_REFCOUNT (src, "src", 4);
510   ASSERT_OBJECT_REFCOUNT (sink, "sink", 3);
511   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 3);
512
513   pop_messages (bus, 6);
514   fail_if ((gst_bus_pop (bus)) != NULL);
515
516   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
517   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
518   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
519
520   /* setting pipeline to NULL flushes the bus automatically */
521   ret = gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
522   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
523
524   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
525   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
526   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
527
528   /* clean up */
529   gst_object_unref (bus);
530   gst_object_unref (pipeline);
531 }
532
533 GST_END_TEST;
534
535 GST_START_TEST (test_watch_for_state_change)
536 {
537   GstElement *src, *sink, *bin;
538   GstBus *bus;
539   GstStateChangeReturn ret;
540
541   bin = gst_element_factory_make ("bin", NULL);
542   fail_unless (bin != NULL, "Could not create bin");
543
544   bus = g_object_new (gst_bus_get_type (), NULL);
545   gst_element_set_bus (GST_ELEMENT_CAST (bin), bus);
546
547   src = gst_element_factory_make ("fakesrc", NULL);
548   fail_if (src == NULL, "Could not create fakesrc");
549   sink = gst_element_factory_make ("fakesink", NULL);
550   fail_if (sink == NULL, "Could not create fakesink");
551
552   gst_bin_add (GST_BIN (bin), sink);
553   gst_bin_add (GST_BIN (bin), src);
554
555   fail_unless (gst_element_link (src, sink), "could not link src and sink");
556
557   /* change state, spawning two times three messages */
558   ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED);
559   fail_unless (ret == GST_STATE_CHANGE_ASYNC);
560   ret =
561       gst_element_get_state (GST_ELEMENT (bin), NULL, NULL,
562       GST_CLOCK_TIME_NONE);
563   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
564
565   pop_messages (bus, 6);
566   pop_async_done (bus);
567
568   fail_unless (gst_bus_have_pending (bus) == FALSE,
569       "Unexpected messages on bus");
570
571   ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PLAYING);
572   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
573
574   pop_messages (bus, 3);
575
576   /* this one might return either SUCCESS or ASYNC, likely SUCCESS */
577   ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED);
578   gst_element_get_state (GST_ELEMENT (bin), NULL, NULL, GST_CLOCK_TIME_NONE);
579
580   pop_messages (bus, 3);
581   if (ret == GST_STATE_CHANGE_ASYNC)
582     pop_async_done (bus);
583
584   fail_unless (gst_bus_have_pending (bus) == FALSE,
585       "Unexpected messages on bus");
586
587   gst_bus_set_flushing (bus, TRUE);
588
589   ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL);
590   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
591
592   /* clean up */
593   gst_object_unref (bus);
594   gst_object_unref (bin);
595 }
596
597 GST_END_TEST;
598
599 GST_START_TEST (test_state_change_error_message)
600 {
601   GstElement *src, *sink, *bin;
602   GstBus *bus;
603   GstStateChangeReturn ret;
604
605   bin = gst_element_factory_make ("bin", NULL);
606   fail_unless (bin != NULL, "Could not create bin");
607
608   bus = g_object_new (gst_bus_get_type (), NULL);
609   gst_element_set_bus (GST_ELEMENT_CAST (bin), bus);
610
611   src = gst_element_factory_make ("fakesrc", NULL);
612   fail_if (src == NULL, "Could not create fakesrc");
613   sink = gst_element_factory_make ("fakesink", NULL);
614   fail_if (sink == NULL, "Could not create fakesink");
615
616   /* add but don't link elements */
617   gst_bin_add (GST_BIN (bin), sink);
618   gst_bin_add (GST_BIN (bin), src);
619
620   /* change state, this should succeed */
621   ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED);
622   fail_unless (ret == GST_STATE_CHANGE_ASYNC);
623
624   /* now wait, the streaming thread will error because the source is not
625    * linked. */
626   ret = gst_element_get_state (GST_ELEMENT (bin), NULL, NULL,
627       GST_CLOCK_TIME_NONE);
628   fail_unless (ret == GST_STATE_CHANGE_FAILURE);
629
630   gst_bus_set_flushing (bus, TRUE);
631
632   /* setting bin to NULL flushes the bus automatically */
633   ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL);
634   fail_unless (ret == GST_STATE_CHANGE_SUCCESS);
635
636   /* clean up */
637   gst_object_unref (bus);
638   gst_object_unref (bin);
639 }
640
641 GST_END_TEST;
642
643
644 /* adding an element with linked pads to a bin unlinks the
645  * pads */
646 GST_START_TEST (test_add_linked)
647 {
648   GstElement *src, *sink;
649   GstPad *srcpad, *sinkpad;
650   GstElement *pipeline;
651
652   pipeline = gst_pipeline_new (NULL);
653   fail_unless (pipeline != NULL, "Could not create pipeline");
654
655   src = gst_element_factory_make ("fakesrc", NULL);
656   fail_if (src == NULL, "Could not create fakesrc");
657   sink = gst_element_factory_make ("fakesink", NULL);
658   fail_if (sink == NULL, "Could not create fakesink");
659
660   srcpad = gst_element_get_static_pad (src, "src");
661   fail_unless (srcpad != NULL);
662   sinkpad = gst_element_get_static_pad (sink, "sink");
663   fail_unless (sinkpad != NULL);
664
665   fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK);
666
667   /* pads are linked now */
668   fail_unless (gst_pad_is_linked (srcpad));
669   fail_unless (gst_pad_is_linked (sinkpad));
670
671   /* adding element to bin voids hierarchy so pads are unlinked */
672   gst_bin_add (GST_BIN (pipeline), src);
673
674   /* check if pads really are unlinked */
675   fail_unless (!gst_pad_is_linked (srcpad));
676   fail_unless (!gst_pad_is_linked (sinkpad));
677
678   /* cannot link pads in wrong hierarchy */
679   fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_WRONG_HIERARCHY);
680
681   /* adding other element to bin as well */
682   gst_bin_add (GST_BIN (pipeline), sink);
683
684   /* now we can link again */
685   fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK);
686
687   /* check if pads really are linked */
688   fail_unless (gst_pad_is_linked (srcpad));
689   fail_unless (gst_pad_is_linked (sinkpad));
690
691   gst_object_unref (srcpad);
692   gst_object_unref (sinkpad);
693   gst_object_unref (pipeline);
694 }
695
696 GST_END_TEST;
697
698 /* adding ourself should fail */
699 GST_START_TEST (test_add_self)
700 {
701   GstElement *bin;
702
703   bin = gst_bin_new (NULL);
704   fail_unless (bin != NULL, "Could not create bin");
705
706   ASSERT_CRITICAL (gst_bin_add (GST_BIN (bin), bin));
707
708   gst_object_unref (bin);
709 }
710
711 GST_END_TEST;
712
713
714 /* g_print ("%10s: %4d => %4d\n", GST_OBJECT_NAME (msg->src), old, new); */
715
716 #define ASSERT_STATE_CHANGE_MSG(bus,element,old_state,new_state,num)          \
717   {                                                                           \
718     GstMessage *msg;                                                          \
719     GstState old = 0, new = 0, pending = 0;                                   \
720     msg = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, GST_SECOND);          \
721     fail_if (msg == NULL, "No state change message within 1 second (#"        \
722         G_STRINGIFY (num) ")");                                               \
723     gst_message_parse_state_changed (msg, &old, &new, &pending);              \
724     fail_if (msg->src != GST_OBJECT (element), G_STRINGIFY(element)           \
725         " should have changed state next (#" G_STRINGIFY (num) ")");          \
726     fail_if (old != old_state || new != new_state, "state change is not "     \
727         G_STRINGIFY (old_state) " => " G_STRINGIFY (new_state));              \
728     gst_message_unref (msg);                                                  \
729   }
730
731 GST_START_TEST (test_children_state_change_order_flagged_sink)
732 {
733   GstElement *src, *identity, *sink, *pipeline;
734   GstStateChangeReturn ret;
735   GstState current, pending;
736   GstBus *bus;
737
738   pipeline = gst_pipeline_new (NULL);
739   fail_unless (pipeline != NULL, "Could not create pipeline");
740
741   bus = gst_element_get_bus (pipeline);
742   fail_unless (bus != NULL, "Pipeline has no bus?!");
743
744   src = gst_element_factory_make ("fakesrc", NULL);
745   fail_if (src == NULL, "Could not create fakesrc");
746   g_object_set (src, "num-buffers", 5, NULL);
747
748   identity = gst_element_factory_make ("identity", NULL);
749   fail_if (identity == NULL, "Could not create identity");
750
751   sink = gst_element_factory_make ("fakesink", NULL);
752   fail_if (sink == NULL, "Could not create fakesink");
753
754   gst_bin_add_many (GST_BIN (pipeline), src, identity, sink, NULL);
755
756   fail_unless (gst_element_link (src, identity) == TRUE);
757   fail_unless (gst_element_link (identity, sink) == TRUE);
758
759   /* (1) Test state change with fakesink being a regular sink */
760   ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
761   fail_if (ret != GST_STATE_CHANGE_ASYNC,
762       "State change to PLAYING did not return ASYNC");
763   ret =
764       gst_element_get_state (pipeline, &current, &pending, GST_CLOCK_TIME_NONE);
765   fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to PLAYING failed");
766   fail_if (current != GST_STATE_PLAYING, "State change to PLAYING failed");
767   fail_if (pending != GST_STATE_VOID_PENDING, "State change to PLAYING failed");
768
769   /* NULL => READY */
770   ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_NULL, GST_STATE_READY, 101);
771   ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_NULL, GST_STATE_READY, 102);
772   ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_NULL, GST_STATE_READY, 103);
773   ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_NULL, GST_STATE_READY, 104);
774
775   /* READY => PAUSED */
776   /* because of pre-rolling, sink will return ASYNC on state
777    * change and change state later when it has a buffer */
778   GST_DEBUG ("popping READY -> PAUSED messages");
779   ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_READY, GST_STATE_PAUSED,
780       105);
781 #if 0
782   /* From here on, all bets are off. Usually the source changes state next,
783    * but it might just as well be that the first buffer produced by the
784    * source reaches the sink before the source has finished its state change,
785    * in which case the sink will commit its new state before the source ...  */
786   ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_READY, GST_STATE_PAUSED, 106);
787   ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_READY, GST_STATE_PAUSED, 107);
788 #else
789
790   pop_messages (bus, 2);        /* pop remaining ready => paused messages off the bus */
791   ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_READY, GST_STATE_PAUSED,
792       108);
793   pop_async_done (bus);
794 #endif
795   /* PAUSED => PLAYING */
796   GST_DEBUG ("popping PAUSED -> PLAYING messages");
797   ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_PAUSED, GST_STATE_PLAYING, 109);
798   ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_PAUSED, GST_STATE_PLAYING,
799       110);
800   ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_PAUSED, GST_STATE_PLAYING, 111);
801   ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_PAUSED, GST_STATE_PLAYING,
802       112);
803
804   /* don't set to NULL that will set the bus flushing and kill our messages */
805   ret = gst_element_set_state (pipeline, GST_STATE_READY);
806   fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to READY failed");
807   ret = gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
808   fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to READY failed");
809
810   /* TODO: do we need to check downwards state change order as well? */
811   pop_messages (bus, 4);        /* pop playing => paused messages off the bus */
812   pop_messages (bus, 4);        /* pop paused => ready messages off the bus */
813
814   while (GST_OBJECT_REFCOUNT_VALUE (pipeline) > 1)
815     THREAD_SWITCH ();
816
817   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
818   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
819   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
820
821   ret = gst_element_set_state (pipeline, GST_STATE_NULL);
822   fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to NULL failed");
823
824   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
825   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
826   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
827
828   gst_object_unref (bus);
829   gst_object_unref (pipeline);
830 }
831
832 GST_END_TEST;
833
834
835 GST_START_TEST (test_children_state_change_order_semi_sink)
836 {
837   GstElement *src, *identity, *sink, *pipeline;
838   GstStateChangeReturn ret;
839   GstState current, pending;
840   GstBus *bus;
841
842   /* (2) Now again, but check other code path where we don't have
843    *     a proper sink correctly flagged as such, but a 'semi-sink' */
844   pipeline = gst_pipeline_new (NULL);
845   fail_unless (pipeline != NULL, "Could not create pipeline");
846
847   bus = gst_element_get_bus (pipeline);
848   fail_unless (bus != NULL, "Pipeline has no bus?!");
849
850   src = gst_element_factory_make ("fakesrc", NULL);
851   fail_if (src == NULL, "Could not create fakesrc");
852
853   identity = gst_element_factory_make ("identity", NULL);
854   fail_if (identity == NULL, "Could not create identity");
855
856   sink = gst_element_factory_make ("fakesink", NULL);
857   fail_if (sink == NULL, "Could not create fakesink");
858
859   gst_bin_add_many (GST_BIN (pipeline), src, identity, sink, NULL);
860
861   fail_unless (gst_element_link (src, identity) == TRUE);
862   fail_unless (gst_element_link (identity, sink) == TRUE);
863
864   /* this is not very nice but should work just fine in this case. */
865   GST_OBJECT_FLAG_UNSET (sink, GST_ELEMENT_FLAG_SINK);  /* <======== */
866
867   ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
868   fail_if (ret != GST_STATE_CHANGE_ASYNC, "State change to PLAYING not ASYNC");
869   ret =
870       gst_element_get_state (pipeline, &current, &pending, GST_CLOCK_TIME_NONE);
871   fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to PLAYING failed");
872   fail_if (current != GST_STATE_PLAYING, "State change to PLAYING failed");
873   fail_if (pending != GST_STATE_VOID_PENDING, "State change to PLAYING failed");
874
875   /* NULL => READY */
876   ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_NULL, GST_STATE_READY, 201);
877   ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_NULL, GST_STATE_READY, 202);
878   ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_NULL, GST_STATE_READY, 203);
879   ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_NULL, GST_STATE_READY, 204);
880
881   /* READY => PAUSED */
882   /* because of pre-rolling, sink will return ASYNC on state
883    * change and change state later when it has a buffer */
884   GST_DEBUG ("popping READY -> PAUSED messages");
885   ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_READY, GST_STATE_PAUSED,
886       205);
887 #if 0
888   /* From here on, all bets are off. Usually the source changes state next,
889    * but it might just as well be that the first buffer produced by the
890    * source reaches the sink before the source has finished its state change,
891    * in which case the sink will commit its new state before the source ...  */
892   ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_READY, GST_STATE_PAUSED, 206);
893   ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_READY, GST_STATE_PAUSED, 207);
894 #else
895   pop_messages (bus, 2);        /* pop remaining ready => paused messages off the bus */
896   ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_READY, GST_STATE_PAUSED,
897       208);
898   pop_async_done (bus);
899
900   /* PAUSED => PLAYING */
901   GST_DEBUG ("popping PAUSED -> PLAYING messages");
902   ASSERT_STATE_CHANGE_MSG (bus, sink, GST_STATE_PAUSED, GST_STATE_PLAYING, 209);
903   ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_PAUSED, GST_STATE_PLAYING,
904       210);
905   ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_PAUSED, GST_STATE_PLAYING, 211);
906   ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_PAUSED, GST_STATE_PLAYING,
907       212);
908 #endif
909
910   /* don't set to NULL that will set the bus flushing and kill our messages */
911   ret = gst_element_set_state (pipeline, GST_STATE_READY);
912   fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to READY failed");
913
914   /* TODO: do we need to check downwards state change order as well? */
915   pop_messages (bus, 4);        /* pop playing => paused messages off the bus */
916   pop_messages (bus, 4);        /* pop paused => ready messages off the bus */
917
918   GST_DEBUG ("waiting for pipeline to reach refcount 1");
919   while (GST_OBJECT_REFCOUNT_VALUE (pipeline) > 1)
920     THREAD_SWITCH ();
921
922   GST_DEBUG ("checking refcount");
923   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
924   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
925   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
926
927   ret = gst_element_set_state (pipeline, GST_STATE_NULL);
928   fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to NULL failed");
929
930   GST_DEBUG ("checking refcount");
931   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
932   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
933   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
934
935   GST_DEBUG ("cleanup");
936   gst_object_unref (bus);
937   gst_object_unref (pipeline);
938 }
939
940 GST_END_TEST;
941
942 GST_START_TEST (test_children_state_change_order_two_sink)
943 {
944   GstElement *src, *tee, *identity, *sink1, *sink2, *pipeline;
945   GstStateChangeReturn ret;
946   GstBus *bus;
947
948   pipeline = gst_pipeline_new (NULL);
949   fail_unless (pipeline != NULL, "Could not create pipeline");
950
951   bus = gst_element_get_bus (pipeline);
952   fail_unless (bus != NULL, "Pipeline has no bus?!");
953
954   src = gst_element_factory_make ("fakesrc", NULL);
955   fail_if (src == NULL, "Could not create fakesrc");
956
957   tee = gst_element_factory_make ("tee", NULL);
958   fail_if (tee == NULL, "Could not create tee");
959
960   identity = gst_element_factory_make ("identity", NULL);
961   fail_if (identity == NULL, "Could not create identity");
962
963   sink1 = gst_element_factory_make ("fakesink", NULL);
964   fail_if (sink1 == NULL, "Could not create fakesink1");
965
966   sink2 = gst_element_factory_make ("fakesink", NULL);
967   fail_if (sink2 == NULL, "Could not create fakesink2");
968
969   gst_bin_add_many (GST_BIN (pipeline), src, tee, identity, sink1, sink2, NULL);
970
971   fail_unless (gst_element_link (src, tee) == TRUE);
972   fail_unless (gst_element_link (tee, identity) == TRUE);
973   fail_unless (gst_element_link (identity, sink1) == TRUE);
974   fail_unless (gst_element_link (tee, sink2) == TRUE);
975
976   ret = gst_element_set_state (pipeline, GST_STATE_READY);
977   fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to READY failed");
978
979   /* NULL => READY */
980   {
981     GstMessage *msg;
982     GstState old = 0, new = 0, pending = 0;
983     GstObject *first, *second;
984
985     msg = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, GST_SECOND);
986     fail_if (msg == NULL, "No state change message within 1 second (#201)");
987
988     gst_message_parse_state_changed (msg, &old, &new, &pending);
989     first = gst_object_ref (msg->src);
990
991     fail_if (first != GST_OBJECT (sink1) && first != GST_OBJECT (sink2),
992         "sink1 or sink2 should have changed state next #(202)");
993     gst_message_unref (msg);
994
995     msg = gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, GST_SECOND);
996     fail_if (msg == NULL, "No state change message within 1 second (#201)");
997
998     gst_message_parse_state_changed (msg, &old, &new, &pending);
999     second = gst_object_ref (msg->src);
1000
1001     fail_if (second != GST_OBJECT (sink1) && second != GST_OBJECT (sink2),
1002         "sink1 or sink2 should have changed state next #(202)");
1003     gst_message_unref (msg);
1004
1005     fail_if (second == first, "got state change from same object");
1006
1007     gst_object_unref (first);
1008     gst_object_unref (second);
1009   }
1010   ASSERT_STATE_CHANGE_MSG (bus, identity, GST_STATE_NULL, GST_STATE_READY, 203);
1011   ASSERT_STATE_CHANGE_MSG (bus, tee, GST_STATE_NULL, GST_STATE_READY, 204);
1012   ASSERT_STATE_CHANGE_MSG (bus, src, GST_STATE_NULL, GST_STATE_READY, 205);
1013   ASSERT_STATE_CHANGE_MSG (bus, pipeline, GST_STATE_NULL, GST_STATE_READY, 206);
1014
1015   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
1016   ASSERT_OBJECT_REFCOUNT (tee, "tee", 1);
1017   ASSERT_OBJECT_REFCOUNT (identity, "identity", 1);
1018   ASSERT_OBJECT_REFCOUNT (sink1, "sink1", 1);
1019   ASSERT_OBJECT_REFCOUNT (sink2, "sink2", 1);
1020   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
1021
1022   ret = gst_element_set_state (pipeline, GST_STATE_NULL);
1023   fail_if (ret != GST_STATE_CHANGE_SUCCESS, "State change to NULL failed");
1024
1025   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
1026   ASSERT_OBJECT_REFCOUNT (tee, "tee", 1);
1027   ASSERT_OBJECT_REFCOUNT (identity, "identity", 1);
1028   ASSERT_OBJECT_REFCOUNT (sink1, "sink1", 1);
1029   ASSERT_OBJECT_REFCOUNT (sink2, "sink2", 1);
1030   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
1031
1032   gst_object_unref (bus);
1033   gst_object_unref (pipeline);
1034 }
1035
1036 GST_END_TEST;
1037
1038 GST_START_TEST (test_iterate_sorted)
1039 {
1040   GstElement *src, *tee, *identity, *sink1, *sink2, *pipeline, *bin;
1041   GstIterator *it;
1042   GValue elem = { 0, };
1043
1044   pipeline = gst_pipeline_new (NULL);
1045   fail_unless (pipeline != NULL, "Could not create pipeline");
1046
1047   bin = gst_bin_new (NULL);
1048   fail_unless (bin != NULL, "Could not create bin");
1049
1050   src = gst_element_factory_make ("fakesrc", NULL);
1051   fail_if (src == NULL, "Could not create fakesrc");
1052
1053   tee = gst_element_factory_make ("tee", NULL);
1054   fail_if (tee == NULL, "Could not create tee");
1055
1056   sink1 = gst_element_factory_make ("fakesink", NULL);
1057   fail_if (sink1 == NULL, "Could not create fakesink1");
1058
1059   gst_bin_add_many (GST_BIN (bin), src, tee, sink1, NULL);
1060
1061   fail_unless (gst_element_link (src, tee) == TRUE);
1062   fail_unless (gst_element_link (tee, sink1) == TRUE);
1063
1064   identity = gst_element_factory_make ("identity", NULL);
1065   fail_if (identity == NULL, "Could not create identity");
1066
1067   sink2 = gst_element_factory_make ("fakesink", NULL);
1068   fail_if (sink2 == NULL, "Could not create fakesink2");
1069
1070   gst_bin_add_many (GST_BIN (pipeline), bin, identity, sink2, NULL);
1071
1072   fail_unless (gst_element_link (tee, identity) == TRUE);
1073   fail_unless (gst_element_link (identity, sink2) == TRUE);
1074
1075   it = gst_bin_iterate_sorted (GST_BIN (pipeline));
1076   fail_unless (gst_iterator_next (it, &elem) == GST_ITERATOR_OK);
1077   fail_unless (g_value_get_object (&elem) == (gpointer) sink2);
1078   g_value_reset (&elem);
1079
1080   fail_unless (gst_iterator_next (it, &elem) == GST_ITERATOR_OK);
1081   fail_unless (g_value_get_object (&elem) == (gpointer) identity);
1082   g_value_reset (&elem);
1083
1084   fail_unless (gst_iterator_next (it, &elem) == GST_ITERATOR_OK);
1085   fail_unless (g_value_get_object (&elem) == (gpointer) bin);
1086   g_value_reset (&elem);
1087
1088   g_value_unset (&elem);
1089   gst_iterator_free (it);
1090
1091   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
1092   gst_object_unref (pipeline);
1093 }
1094
1095 GST_END_TEST;
1096
1097 static void
1098 test_link_structure_change_state_changed_sync_cb (GstBus * bus,
1099     GstMessage * message, gpointer data)
1100 {
1101   GstPipeline *pipeline = GST_PIPELINE (data);
1102   GstElement *src, *identity, *sink;
1103   GstState old, snew, pending;
1104
1105   sink = gst_bin_get_by_name (GST_BIN (pipeline), "sink");
1106   fail_unless (sink != NULL, "Could not get sink");
1107
1108   gst_message_parse_state_changed (message, &old, &snew, &pending);
1109   if (message->src != GST_OBJECT (sink) || snew != GST_STATE_READY) {
1110     gst_object_unref (sink);
1111     return;
1112   }
1113
1114   src = gst_bin_get_by_name (GST_BIN (pipeline), "src");
1115   fail_unless (src != NULL, "Could not get src");
1116
1117   identity = gst_bin_get_by_name (GST_BIN (pipeline), "identity");
1118   fail_unless (identity != NULL, "Could not get identity");
1119
1120   /* link src to identity, the pipeline should detect the new link and
1121    * resync the state change */
1122   fail_unless (gst_element_link (src, identity) == TRUE);
1123
1124   gst_object_unref (src);
1125   gst_object_unref (identity);
1126   gst_object_unref (sink);
1127 }
1128
1129 GST_START_TEST (test_link_structure_change)
1130 {
1131   GstElement *src, *identity, *sink, *pipeline;
1132   GstBus *bus;
1133   GstState state;
1134
1135   pipeline = gst_pipeline_new (NULL);
1136   fail_unless (pipeline != NULL, "Could not create pipeline");
1137
1138   bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
1139   fail_unless (bus != NULL, "Could not get bus");
1140
1141   /* use the sync signal handler to link elements while the pipeline is still
1142    * doing the state change */
1143   gst_bus_set_sync_handler (bus, gst_bus_sync_signal_handler, pipeline, NULL);
1144   g_object_connect (bus, "signal::sync-message::state-changed",
1145       G_CALLBACK (test_link_structure_change_state_changed_sync_cb), pipeline,
1146       NULL);
1147
1148   src = gst_element_factory_make ("fakesrc", "src");
1149   fail_if (src == NULL, "Could not create fakesrc");
1150
1151   identity = gst_element_factory_make ("identity", "identity");
1152   fail_if (identity == NULL, "Could not create identity");
1153
1154   sink = gst_element_factory_make ("fakesink", "sink");
1155   fail_if (sink == NULL, "Could not create fakesink1");
1156
1157   gst_bin_add_many (GST_BIN (pipeline), src, identity, sink, NULL);
1158
1159   gst_element_set_state (pipeline, GST_STATE_READY);
1160   gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
1161
1162   /* the state change will be done on src only if the pipeline correctly resyncs
1163    * after that fakesrc has been linked to identity */
1164   gst_element_get_state (src, &state, NULL, 0);
1165   fail_unless_equals_int (state, GST_STATE_READY);
1166
1167   /* clean up */
1168   gst_element_set_state (pipeline, GST_STATE_NULL);
1169   gst_object_unref (bus);
1170   gst_object_unref (pipeline);
1171 }
1172
1173 GST_END_TEST;
1174
1175 static GstBusSyncReply
1176 sync_handler_remove_sink (GstBus * bus, GstMessage * message, gpointer data)
1177 {
1178   if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ERROR) {
1179     GstElement *child;
1180
1181     child = gst_bin_get_by_name (GST_BIN (data), "fakesink");
1182     fail_unless (child != NULL, "Could not find fakesink");
1183
1184     gst_bin_remove (GST_BIN (data), child);
1185     gst_object_unref (child);
1186   }
1187   return GST_BUS_PASS;
1188 }
1189
1190 GST_START_TEST (test_state_failure_remove)
1191 {
1192   GstElement *src, *sink, *pipeline;
1193   GstBus *bus;
1194   GstStateChangeReturn ret;
1195
1196   pipeline = gst_pipeline_new (NULL);
1197   fail_unless (pipeline != NULL, "Could not create pipeline");
1198
1199   src = gst_element_factory_make ("fakesrc", "fakesrc");
1200   fail_unless (src != NULL, "Could not create fakesrc");
1201
1202   sink = gst_element_factory_make ("fakesink", "fakesink");
1203   fail_unless (sink != NULL, "Could not create fakesink");
1204
1205   g_object_set (sink, "state-error", 1, NULL);
1206
1207   gst_bin_add (GST_BIN (pipeline), src);
1208   gst_bin_add (GST_BIN (pipeline), sink);
1209
1210   gst_element_link (src, sink);
1211
1212   bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
1213   fail_unless (bus != NULL, "Could not get bus");
1214
1215   gst_bus_set_sync_handler (bus, sync_handler_remove_sink, pipeline, NULL);
1216
1217   ret = gst_element_set_state (pipeline, GST_STATE_READY);
1218   fail_unless (ret == GST_STATE_CHANGE_SUCCESS,
1219       "did not get state change success");
1220
1221   gst_element_set_state (pipeline, GST_STATE_NULL);
1222
1223   gst_object_unref (bus);
1224   gst_object_unref (pipeline);
1225 }
1226
1227 GST_END_TEST;
1228
1229 GST_START_TEST (test_many_bins)
1230 {
1231   GstStateChangeReturn ret;
1232   GstElement *src, *sink, *pipeline, *last_bin = NULL;
1233   gint i;
1234
1235 #define NUM_BINS 2000
1236
1237   pipeline = gst_pipeline_new (NULL);
1238   fail_unless (pipeline != NULL, "Could not create pipeline");
1239
1240   src = gst_element_factory_make ("fakesrc", "fakesrc");
1241   fail_unless (src != NULL, "Could not create fakesrc");
1242   g_object_set (src, "num-buffers", 3, NULL);
1243
1244   sink = gst_element_factory_make ("fakesink", "fakesink");
1245   fail_unless (sink != NULL, "Could not create fakesink");
1246
1247   gst_bin_add (GST_BIN (pipeline), src);
1248   gst_bin_add (GST_BIN (pipeline), sink);
1249
1250   for (i = 0; i < NUM_BINS; ++i) {
1251     GstElement *bin, *identity;
1252     GstPad *srcpad, *sinkpad;
1253
1254     bin = gst_bin_new (NULL);
1255     fail_unless (bin != NULL, "Could not create bin %d", i);
1256     identity = gst_element_factory_make ("identity", "identity");
1257     fail_unless (identity != NULL, "Could not create identity %d", i);
1258     g_object_set (identity, "silent", TRUE, NULL);
1259     gst_bin_add (GST_BIN (bin), identity);
1260     sinkpad = gst_element_get_static_pad (identity, "sink");
1261     srcpad = gst_element_get_static_pad (identity, "src");
1262     gst_element_add_pad (bin, gst_ghost_pad_new ("sink", sinkpad));
1263     gst_element_add_pad (bin, gst_ghost_pad_new ("src", srcpad));
1264     gst_object_unref (sinkpad);
1265     gst_object_unref (srcpad);
1266
1267     gst_bin_add (GST_BIN (pipeline), bin);
1268
1269     if (last_bin == NULL) {
1270       srcpad = gst_element_get_static_pad (src, "src");
1271     } else {
1272       srcpad = gst_element_get_static_pad (last_bin, "src");
1273     }
1274     sinkpad = gst_element_get_static_pad (bin, "sink");
1275     gst_pad_link_full (srcpad, sinkpad, GST_PAD_LINK_CHECK_NOTHING);
1276     gst_object_unref (sinkpad);
1277     gst_object_unref (srcpad);
1278
1279
1280     last_bin = bin;
1281
1282     /* insert some queues to limit the number of function calls in a row */
1283     if ((i % 100) == 0) {
1284       GstElement *q = gst_element_factory_make ("queue", NULL);
1285
1286       GST_LOG ("bin #%d, inserting queue", i);
1287       gst_bin_add (GST_BIN (pipeline), q);
1288       fail_unless (gst_element_link (last_bin, q));
1289       last_bin = q;
1290     }
1291   }
1292
1293   fail_unless (gst_element_link (last_bin, sink));
1294
1295   ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
1296   fail_unless_equals_int (ret, GST_STATE_CHANGE_ASYNC);
1297
1298   for (i = 0; i < 15; ++i) {
1299     GST_INFO ("waiting for preroll ...");
1300     ret = gst_element_get_state (pipeline, NULL, NULL, GST_SECOND);
1301     if (ret != GST_STATE_CHANGE_ASYNC)
1302       break;
1303   }
1304   fail_unless_equals_int (ret, GST_STATE_CHANGE_SUCCESS);
1305
1306   gst_element_set_state (pipeline, GST_STATE_NULL);
1307   gst_object_unref (pipeline);
1308 }
1309
1310 GST_END_TEST;
1311
1312 static GstPadProbeReturn
1313 fakesrc_pad_blocked_cb (GstPad * pad, GstPadProbeInfo * info, void *arg)
1314 {
1315   GstPipeline *pipeline = (GstPipeline *) arg;
1316   GstElement *src, *sink;
1317
1318   src = gst_bin_get_by_name (GST_BIN (pipeline), "fakesrc");
1319   fail_unless (src != NULL, "Could not get fakesrc");
1320
1321   sink = gst_element_factory_make ("fakesink", "fakesink");
1322   fail_unless (sink != NULL, "Could not create fakesink");
1323
1324   g_object_set (sink, "state-error", 1, NULL);
1325   gst_bin_add (GST_BIN (pipeline), sink);
1326
1327   gst_element_link (src, sink);
1328   gst_element_sync_state_with_parent (sink);
1329   gst_object_unref (src);
1330
1331   return GST_PAD_PROBE_REMOVE;
1332 }
1333
1334 GST_START_TEST (test_state_failure_unref)
1335 {
1336   GstElement *src, *pipeline;
1337   GstPad *srcpad;
1338   GstBus *bus;
1339   GstStateChangeReturn ret;
1340   GstMessage *msg;
1341
1342   pipeline = gst_pipeline_new (NULL);
1343   fail_unless (pipeline != NULL, "Could not create pipeline");
1344
1345   src = gst_element_factory_make ("fakesrc", "fakesrc");
1346   fail_unless (src != NULL, "Could not create fakesrc");
1347
1348   srcpad = gst_element_get_static_pad (src, "src");
1349   fail_unless (srcpad != NULL, "Could not get fakesrc srcpad");
1350
1351   gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
1352       fakesrc_pad_blocked_cb, pipeline, NULL);
1353   gst_object_unref (srcpad);
1354
1355   gst_bin_add (GST_BIN (pipeline), src);
1356
1357   bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
1358   fail_unless (bus != NULL, "Could not get bus");
1359
1360   gst_element_set_state (pipeline, GST_STATE_PLAYING);
1361
1362   /* Wait for an error message from our fakesink (added from the
1363      pad block callback). */
1364   msg = gst_bus_poll (bus, GST_MESSAGE_ERROR, GST_SECOND);
1365   fail_if (msg == NULL, "No error message within 1 second");
1366   gst_message_unref (msg);
1367
1368   /* Check that after this failure, we can still stop, and then unref, the
1369      pipeline. This should always be possible. */
1370   ret = gst_element_set_state (pipeline, GST_STATE_NULL);
1371   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "downward state change failed");
1372
1373   gst_object_unref (bus);
1374   gst_object_unref (pipeline);
1375 }
1376
1377 GST_END_TEST;
1378
1379 static void
1380 on_sync_bus_error (GstBus * bus, GstMessage * msg)
1381 {
1382   fail_if (msg != NULL);
1383 }
1384
1385 GST_START_TEST (test_state_change_skip)
1386 {
1387   GstElement *sink, *pipeline;
1388   GstStateChangeReturn ret;
1389   GstBus *bus;
1390
1391   pipeline = gst_pipeline_new (NULL);
1392   fail_unless (pipeline != NULL, "Could not create pipeline");
1393
1394   bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
1395   fail_unless (bus != NULL, "Could not get bus");
1396
1397   /* no errors */
1398   gst_bus_enable_sync_message_emission (bus);
1399   g_signal_connect (bus, "sync-message::error", (GCallback) on_sync_bus_error,
1400       NULL);
1401
1402   sink = gst_element_factory_make ("fakesink", "fakesink");
1403   fail_unless (sink != NULL, "Could not create fakesink");
1404   gst_element_set_state (sink, GST_STATE_PAUSED);
1405
1406   g_object_set (sink, "state-error", 5, NULL);
1407
1408   gst_bin_add (GST_BIN (pipeline), sink);
1409   gst_element_set_state (pipeline, GST_STATE_PLAYING);
1410
1411   g_object_set (sink, "state-error", 0, NULL);
1412
1413   /* Check that after this failure, we can still stop, and then unref, the
1414      pipeline. This should always be possible. */
1415   ret = gst_element_set_state (pipeline, GST_STATE_NULL);
1416   fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "downward state change failed");
1417
1418   gst_object_unref (pipeline);
1419   gst_object_unref (bus);
1420 }
1421
1422 GST_END_TEST;
1423
1424 GST_START_TEST (test_duration_is_max)
1425 {
1426   GstElement *bin, *src[3], *sink[3];
1427   GstStateChangeReturn state_res;
1428   GstFormat format = GST_FORMAT_BYTES;
1429   gboolean res;
1430   gint64 duration;
1431   GstBus *bus;
1432
1433   GST_INFO ("preparing test");
1434
1435   /* build pipeline */
1436   bin = gst_pipeline_new ("pipeline");
1437
1438   /* 3 sources, an adder and a fakesink */
1439   src[0] = gst_element_factory_make ("fakesrc", NULL);
1440   src[1] = gst_element_factory_make ("fakesrc", NULL);
1441   src[2] = gst_element_factory_make ("fakesrc", NULL);
1442   sink[0] = gst_element_factory_make ("fakesink", NULL);
1443   sink[1] = gst_element_factory_make ("fakesink", NULL);
1444   sink[2] = gst_element_factory_make ("fakesink", NULL);
1445   gst_bin_add_many (GST_BIN (bin), src[0], src[1], src[2], sink[0], sink[1],
1446       sink[2], NULL);
1447
1448   gst_element_link (src[0], sink[0]);
1449   gst_element_link (src[1], sink[1]);
1450   gst_element_link (src[2], sink[2]);
1451
1452   /* irks, duration is reset on basesrc */
1453   state_res = gst_element_set_state (bin, GST_STATE_PAUSED);
1454   fail_unless (state_res != GST_STATE_CHANGE_FAILURE, NULL);
1455
1456   /* set durations on src */
1457   GST_BASE_SRC (src[0])->segment.duration = 1000;
1458   GST_BASE_SRC (src[1])->segment.duration = 3000;
1459   GST_BASE_SRC (src[2])->segment.duration = 2000;
1460
1461   /* set to playing */
1462   state_res = gst_element_set_state (bin, GST_STATE_PLAYING);
1463   fail_unless (state_res != GST_STATE_CHANGE_FAILURE, NULL);
1464
1465   /* wait for completion */
1466   state_res =
1467       gst_element_get_state (GST_ELEMENT (bin), NULL, NULL,
1468       GST_CLOCK_TIME_NONE);
1469   fail_unless (state_res != GST_STATE_CHANGE_FAILURE, NULL);
1470
1471   res = gst_element_query_duration (GST_ELEMENT (bin), format, &duration);
1472   fail_unless (res, NULL);
1473
1474   ck_assert_int_eq (duration, 3000);
1475
1476   bus = gst_element_get_bus (bin);
1477   gst_bus_set_flushing (bus, TRUE);
1478   gst_object_unref (bus);
1479
1480   gst_element_set_state (bin, GST_STATE_NULL);
1481   gst_object_unref (bin);
1482 }
1483
1484 GST_END_TEST;
1485
1486 GST_START_TEST (test_duration_unknown_overrides)
1487 {
1488   GstElement *bin, *src[3], *sink[3];
1489   GstStateChangeReturn state_res;
1490   GstFormat format = GST_FORMAT_BYTES;
1491   gboolean res;
1492   gint64 duration;
1493   GstBus *bus;
1494
1495   GST_INFO ("preparing test");
1496
1497   /* build pipeline */
1498   bin = gst_pipeline_new ("pipeline");
1499
1500   /* 3 sources, an adder and a fakesink */
1501   src[0] = gst_element_factory_make ("fakesrc", NULL);
1502   src[1] = gst_element_factory_make ("fakesrc", NULL);
1503   src[2] = gst_element_factory_make ("fakesrc", NULL);
1504   sink[0] = gst_element_factory_make ("fakesink", NULL);
1505   sink[1] = gst_element_factory_make ("fakesink", NULL);
1506   sink[2] = gst_element_factory_make ("fakesink", NULL);
1507   gst_bin_add_many (GST_BIN (bin), src[0], src[1], src[2], sink[0], sink[1],
1508       sink[2], NULL);
1509
1510   gst_element_link (src[0], sink[0]);
1511   gst_element_link (src[1], sink[1]);
1512   gst_element_link (src[2], sink[2]);
1513
1514   /* irks, duration is reset on basesrc */
1515   state_res = gst_element_set_state (bin, GST_STATE_PAUSED);
1516   fail_unless (state_res != GST_STATE_CHANGE_FAILURE, NULL);
1517
1518   /* set durations on src */
1519   GST_BASE_SRC (src[0])->segment.duration = GST_CLOCK_TIME_NONE;
1520   GST_BASE_SRC (src[1])->segment.duration = 3000;
1521   GST_BASE_SRC (src[2])->segment.duration = 2000;
1522
1523   /* set to playing */
1524   state_res = gst_element_set_state (bin, GST_STATE_PLAYING);
1525   fail_unless (state_res != GST_STATE_CHANGE_FAILURE, NULL);
1526
1527   /* wait for completion */
1528   state_res =
1529       gst_element_get_state (GST_ELEMENT (bin), NULL, NULL,
1530       GST_CLOCK_TIME_NONE);
1531   fail_unless (state_res != GST_STATE_CHANGE_FAILURE, NULL);
1532
1533   res = gst_element_query_duration (GST_ELEMENT (bin), format, &duration);
1534   fail_unless (res, NULL);
1535
1536   ck_assert_int_eq (duration, GST_CLOCK_TIME_NONE);
1537
1538   bus = gst_element_get_bus (bin);
1539   gst_bus_set_flushing (bus, TRUE);
1540   gst_object_unref (bus);
1541
1542   gst_element_set_state (bin, GST_STATE_NULL);
1543   gst_object_unref (bin);
1544 }
1545
1546 GST_END_TEST;
1547
1548 static gboolean
1549 element_in_list (GList ** list, GstElement * element)
1550 {
1551   GList *l = g_list_find (*list, element);
1552
1553   if (l == NULL)
1554     return FALSE;
1555
1556   *list = g_list_delete_link (*list, l);
1557   return TRUE;
1558 }
1559
1560 #define element_was_added(e) element_in_list(&added,e)
1561 #define element_was_removed(e) element_in_list(&removed,e)
1562
1563 static void
1564 add_cb (GstBin * pipeline, GstBin * bin, GstElement * element, GList ** list)
1565 {
1566   fail_unless (GST_OBJECT_PARENT (element) == GST_OBJECT_CAST (bin));
1567
1568   *list = g_list_prepend (*list, element);
1569 }
1570
1571 static void
1572 remove_cb (GstBin * pipeline, GstBin * bin, GstElement * element, GList ** list)
1573 {
1574   *list = g_list_prepend (*list, element);
1575 }
1576
1577 GST_START_TEST (test_deep_added_removed)
1578 {
1579   GstElement *pipe, *e, *bin0, *bin1;
1580   gulong id_removed, id_added;
1581   GList *removed = NULL;
1582   GList *added = NULL;
1583
1584   pipe = gst_pipeline_new (NULL);
1585
1586   id_added = g_signal_connect (pipe, "deep-element-added",
1587       G_CALLBACK (add_cb), &added);
1588   id_removed = g_signal_connect (pipe, "deep-element-removed",
1589       G_CALLBACK (remove_cb), &removed);
1590
1591   /* simple add/remove */
1592   e = gst_element_factory_make ("identity", NULL);
1593   gst_bin_add (GST_BIN (pipe), e);
1594   fail_unless (element_was_added (e));
1595   gst_bin_remove (GST_BIN (pipe), e);
1596   fail_unless (element_was_removed (e));
1597
1598   /* let's try with a deeper hierarchy, construct it from top-level down */
1599   bin0 = gst_bin_new (NULL);
1600   gst_bin_add (GST_BIN (pipe), bin0);
1601   bin1 = gst_bin_new (NULL);
1602   gst_bin_add (GST_BIN (bin0), bin1);
1603   e = gst_element_factory_make ("identity", NULL);
1604   gst_bin_add (GST_BIN (bin1), e);
1605   fail_unless (element_was_added (bin0));
1606   fail_unless (element_was_added (bin1));
1607   fail_unless (element_was_added (e));
1608   fail_unless (added == NULL);
1609   fail_unless (removed == NULL);
1610
1611   gst_object_ref (e);           /* keep e alive */
1612   gst_bin_remove (GST_BIN (bin1), e);
1613   fail_unless (element_was_removed (e));
1614   fail_unless (added == NULL);
1615   fail_unless (removed == NULL);
1616
1617   /* now add existing bin hierarchy to pipeline (first remove it so we can re-add it) */
1618   gst_object_ref (bin0);        /* keep bin0 alive */
1619   gst_bin_remove (GST_BIN (pipe), bin0);
1620   fail_unless (element_was_removed (bin0));
1621   fail_unless (element_was_removed (bin1));
1622   fail_unless (added == NULL);
1623   fail_unless (removed == NULL);
1624
1625   /* re-adding element to removed bin should not trigger our callbacks */
1626   gst_bin_add (GST_BIN (bin1), e);
1627   fail_unless (added == NULL);
1628   fail_unless (removed == NULL);
1629
1630   gst_bin_add (GST_BIN (pipe), bin0);
1631   fail_unless (element_was_added (bin0));
1632   fail_unless (element_was_added (bin1));
1633   fail_unless (element_was_added (e));
1634   fail_unless (added == NULL);
1635   fail_unless (removed == NULL);
1636   gst_object_unref (bin0);
1637   gst_object_unref (e);
1638
1639   /* disconnect signals, unref will trigger remove callbacks otherwise */
1640   g_signal_handler_disconnect (pipe, id_added);
1641   g_signal_handler_disconnect (pipe, id_removed);
1642
1643   gst_object_unref (pipe);
1644 }
1645
1646 GST_END_TEST;
1647
1648 #define _GST_CHECK_BIN_SUPPRESSED_FLAGS(element_flags, suppressed_flags, \
1649     expected_flags) \
1650 G_STMT_START { \
1651   GstBin *bin = GST_BIN (gst_bin_new ("test-bin")); \
1652   GstElement *element = gst_element_factory_make ("identity", "test-i"); \
1653   GstElementFlags natural_flags = GST_OBJECT_FLAGS (bin); \
1654   GST_OBJECT_FLAG_SET (element, element_flags); \
1655   gst_bin_set_suppressed_flags (bin, suppressed_flags); \
1656   gst_bin_add (bin, element); \
1657   fail_unless ((natural_flags | GST_OBJECT_FLAGS (bin)) \
1658       == expected_flags); \
1659   gst_object_unref (bin); \
1660 } G_STMT_END
1661
1662 GST_START_TEST (test_suppressed_flags)
1663 {
1664   _GST_CHECK_BIN_SUPPRESSED_FLAGS (GST_ELEMENT_FLAG_SOURCE,
1665       0, GST_ELEMENT_FLAG_SOURCE);
1666   _GST_CHECK_BIN_SUPPRESSED_FLAGS (GST_ELEMENT_FLAG_SOURCE,
1667       GST_ELEMENT_FLAG_SOURCE, 0);
1668   _GST_CHECK_BIN_SUPPRESSED_FLAGS (GST_ELEMENT_FLAG_SOURCE,
1669       GST_ELEMENT_FLAG_SINK, GST_ELEMENT_FLAG_SOURCE);
1670   _GST_CHECK_BIN_SUPPRESSED_FLAGS (GST_ELEMENT_FLAG_SOURCE |
1671       GST_ELEMENT_FLAG_PROVIDE_CLOCK,
1672       GST_ELEMENT_FLAG_PROVIDE_CLOCK, GST_ELEMENT_FLAG_SOURCE);
1673
1674   _GST_CHECK_BIN_SUPPRESSED_FLAGS (GST_ELEMENT_FLAG_SINK,
1675       0, GST_ELEMENT_FLAG_SINK);
1676   _GST_CHECK_BIN_SUPPRESSED_FLAGS (GST_ELEMENT_FLAG_SINK,
1677       GST_ELEMENT_FLAG_SINK, 0);
1678   _GST_CHECK_BIN_SUPPRESSED_FLAGS (GST_ELEMENT_FLAG_SINK,
1679       GST_ELEMENT_FLAG_SOURCE, GST_ELEMENT_FLAG_SINK);
1680
1681   _GST_CHECK_BIN_SUPPRESSED_FLAGS (GST_ELEMENT_FLAG_PROVIDE_CLOCK,
1682       0, GST_ELEMENT_FLAG_PROVIDE_CLOCK);
1683   _GST_CHECK_BIN_SUPPRESSED_FLAGS (GST_ELEMENT_FLAG_PROVIDE_CLOCK,
1684       GST_ELEMENT_FLAG_PROVIDE_CLOCK, 0);
1685   _GST_CHECK_BIN_SUPPRESSED_FLAGS (GST_ELEMENT_FLAG_PROVIDE_CLOCK,
1686       GST_ELEMENT_FLAG_REQUIRE_CLOCK, GST_ELEMENT_FLAG_PROVIDE_CLOCK);
1687
1688   _GST_CHECK_BIN_SUPPRESSED_FLAGS (GST_ELEMENT_FLAG_REQUIRE_CLOCK,
1689       0, GST_ELEMENT_FLAG_REQUIRE_CLOCK);
1690   _GST_CHECK_BIN_SUPPRESSED_FLAGS (GST_ELEMENT_FLAG_REQUIRE_CLOCK,
1691       GST_ELEMENT_FLAG_REQUIRE_CLOCK, 0);
1692   _GST_CHECK_BIN_SUPPRESSED_FLAGS (GST_ELEMENT_FLAG_REQUIRE_CLOCK,
1693       GST_ELEMENT_FLAG_PROVIDE_CLOCK, GST_ELEMENT_FLAG_REQUIRE_CLOCK);
1694 }
1695
1696 GST_END_TEST;
1697
1698
1699 #define _GST_CHECK_BIN_SUPPRESSED_FLAGS_REMOVAL(suppressed_flags) \
1700 G_STMT_START { \
1701   GstBin *bin = GST_BIN (gst_bin_new ("test-bin")); \
1702   GstElement *element = gst_element_factory_make ("identity", "test-i"); \
1703   GST_OBJECT_FLAG_SET (bin, suppressed_flags); \
1704   gst_bin_set_suppressed_flags (bin, suppressed_flags); \
1705   GST_OBJECT_FLAG_SET (element, suppressed_flags); \
1706   fail_unless ((suppressed_flags & GST_OBJECT_FLAGS (bin)) \
1707       == suppressed_flags); \
1708   gst_bin_add (bin, element); \
1709   fail_unless ((suppressed_flags & GST_OBJECT_FLAGS (bin)) \
1710       == suppressed_flags); \
1711   gst_bin_remove (bin, element); \
1712   fail_unless ((suppressed_flags & GST_OBJECT_FLAGS (bin)) \
1713       == suppressed_flags); \
1714   gst_object_unref (bin); \
1715 } G_STMT_END
1716
1717 GST_START_TEST (test_suppressed_flags_when_removing)
1718 {
1719   _GST_CHECK_BIN_SUPPRESSED_FLAGS_REMOVAL (GST_ELEMENT_FLAG_SOURCE);
1720   _GST_CHECK_BIN_SUPPRESSED_FLAGS_REMOVAL (GST_ELEMENT_FLAG_SINK);
1721   _GST_CHECK_BIN_SUPPRESSED_FLAGS_REMOVAL (GST_ELEMENT_FLAG_REQUIRE_CLOCK);
1722   _GST_CHECK_BIN_SUPPRESSED_FLAGS_REMOVAL (GST_ELEMENT_FLAG_PROVIDE_CLOCK);
1723 }
1724
1725 GST_END_TEST;
1726
1727 static Suite *
1728 gst_bin_suite (void)
1729 {
1730   Suite *s = suite_create ("GstBin");
1731   TCase *tc_chain = tcase_create ("bin tests");
1732
1733   tcase_set_timeout (tc_chain, 0);
1734
1735   suite_add_tcase (s, tc_chain);
1736   tcase_add_test (tc_chain, test_interface);
1737   tcase_add_test (tc_chain, test_eos);
1738   tcase_add_test (tc_chain, test_stream_start);
1739   tcase_add_test (tc_chain, test_children_state_change_order_flagged_sink);
1740   tcase_add_test (tc_chain, test_children_state_change_order_semi_sink);
1741   tcase_add_test (tc_chain, test_children_state_change_order_two_sink);
1742   tcase_add_test (tc_chain, test_message_state_changed);
1743   tcase_add_test (tc_chain, test_message_state_changed_child);
1744   tcase_add_test (tc_chain, test_message_state_changed_children);
1745   tcase_add_test (tc_chain, test_watch_for_state_change);
1746   tcase_add_test (tc_chain, test_state_change_error_message);
1747   tcase_add_test (tc_chain, test_add_linked);
1748   tcase_add_test (tc_chain, test_add_self);
1749   tcase_add_test (tc_chain, test_iterate_sorted);
1750   tcase_add_test (tc_chain, test_link_structure_change);
1751   tcase_add_test (tc_chain, test_state_failure_remove);
1752   tcase_add_test (tc_chain, test_state_failure_unref);
1753   tcase_add_test (tc_chain, test_state_change_skip);
1754   tcase_add_test (tc_chain, test_duration_is_max);
1755   tcase_add_test (tc_chain, test_duration_unknown_overrides);
1756   tcase_add_test (tc_chain, test_deep_added_removed);
1757   tcase_add_test (tc_chain, test_suppressed_flags);
1758   tcase_add_test (tc_chain, test_suppressed_flags_when_removing);
1759
1760   /* fails on OSX build bot for some reason, and is a bit silly anyway */
1761   if (0)
1762     tcase_add_test (tc_chain, test_many_bins);
1763
1764   return s;
1765 }
1766
1767 GST_CHECK_MAIN (gst_bin);