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