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