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