Change GST_MESSAGE_SRC to be a GObject rather than a GstObject, so that applications...
[platform/upstream/gstreamer.git] / 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     fail_unless (gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, -1)
35         == GST_MESSAGE_STATE_CHANGED, "did not get GST_MESSAGE_STATE_CHANGED");
36
37     message = gst_bus_pop (bus);
38     gst_message_unref (message);
39   }
40   GST_DEBUG ("popped %d messages", count);
41 }
42
43 GST_START_TEST (test_interface)
44 {
45   GstBin *bin, *bin2;
46   GstElement *filesrc;
47   GstIterator *it;
48   gpointer item;
49
50   bin = GST_BIN (gst_bin_new (NULL));
51   fail_unless (bin != NULL, "Could not create bin");
52
53   filesrc = gst_element_factory_make ("filesrc", NULL);
54   fail_unless (filesrc != NULL, "Could not create filesrc");
55   fail_unless (GST_IS_URI_HANDLER (filesrc), "Filesrc not a URI handler");
56   gst_bin_add (bin, filesrc);
57
58   fail_unless (gst_bin_get_by_interface (bin, GST_TYPE_URI_HANDLER) == filesrc);
59   it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER);
60   fail_unless (it != NULL);
61   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
62   fail_unless (item == (gpointer) filesrc);
63   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
64   gst_iterator_free (it);
65
66   gst_bin_add_many (bin,
67       gst_element_factory_make ("identity", NULL),
68       gst_element_factory_make ("identity", NULL),
69       gst_element_factory_make ("identity", NULL), NULL);
70   fail_unless (gst_bin_get_by_interface (bin, GST_TYPE_URI_HANDLER) == filesrc);
71   it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER);
72   fail_unless (it != NULL);
73   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
74   fail_unless (item == (gpointer) filesrc);
75   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
76   gst_iterator_free (it);
77
78   bin2 = bin;
79   bin = GST_BIN (gst_bin_new (NULL));
80   fail_unless (bin != NULL);
81   gst_bin_add_many (bin,
82       gst_element_factory_make ("identity", NULL),
83       gst_element_factory_make ("identity", NULL),
84       GST_ELEMENT (bin2), gst_element_factory_make ("identity", NULL), NULL);
85   fail_unless (gst_bin_get_by_interface (bin, GST_TYPE_URI_HANDLER) == filesrc);
86   it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER);
87   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
88   fail_unless (item == (gpointer) filesrc);
89   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
90   gst_iterator_free (it);
91
92   gst_bin_add (bin, gst_element_factory_make ("filesrc", NULL));
93   gst_bin_add (bin2, gst_element_factory_make ("filesrc", NULL));
94   it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER);
95   fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
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_DONE);
99   gst_iterator_free (it);
100
101   gst_object_unref (bin);
102 }
103
104 GST_END_TEST;
105
106 GST_START_TEST (test_message_state_changed)
107 {
108   GstBin *bin;
109   GstBus *bus;
110   GstMessage *message;
111
112   bin = GST_BIN (gst_bin_new (NULL));
113   fail_unless (bin != NULL, "Could not create bin");
114   ASSERT_OBJECT_REFCOUNT (bin, "bin", 1);
115
116   bus = GST_ELEMENT_BUS (bin);
117
118   /* change state, spawning a message, causing an incref on the bin */
119   gst_element_set_state (GST_ELEMENT (bin), GST_STATE_READY);
120
121   ASSERT_OBJECT_REFCOUNT (bin, "bin", 2);
122
123   /* get and unref the message, causing a decref on the bin */
124   fail_unless (gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED,
125           -1) == GST_MESSAGE_STATE_CHANGED,
126       "did not get GST_MESSAGE_STATE_CHANGED");
127
128   message = gst_bus_pop (bus);
129   gst_message_unref (message);
130
131   ASSERT_OBJECT_REFCOUNT (bin, "bin", 1);
132
133   /* clean up */
134   gst_object_unref (bin);
135 }
136
137 GST_END_TEST;
138
139 GST_START_TEST (test_message_state_changed_child)
140 {
141   GstBin *bin;
142   GstElement *src;
143   GstBus *bus;
144   GstMessage *message;
145
146   bin = GST_BIN (gst_bin_new (NULL));
147   fail_unless (bin != NULL, "Could not create bin");
148   ASSERT_OBJECT_REFCOUNT (bin, "bin", 1);
149
150   src = gst_element_factory_make ("fakesrc", NULL);
151   fail_if (src == NULL, "Could not create fakesrc");
152   gst_bin_add (bin, src);
153   ASSERT_OBJECT_REFCOUNT (bin, "bin", 1);
154   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
155
156   bus = GST_ELEMENT_BUS (bin);
157
158   /* change state, spawning two messages:
159    * - first for fakesrc, forwarded to bin's bus, causing incref on fakesrc
160    * - second for bin, causing an incref on the bin */
161   GST_DEBUG ("setting bin to READY");
162   fail_unless (gst_element_set_state (GST_ELEMENT (bin), GST_STATE_READY)
163       == GST_STATE_SUCCESS);
164
165   ASSERT_OBJECT_REFCOUNT (src, "src", 2);
166   ASSERT_OBJECT_REFCOUNT (bin, "bin", 2);
167
168   /* get and unref the message, causing a decref on the src */
169   fail_unless (gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, -1)
170       == GST_MESSAGE_STATE_CHANGED, "did not get GST_MESSAGE_STATE_CHANGED");
171
172   message = gst_bus_pop (bus);
173   fail_unless (GST_MESSAGE_SRC (message) == G_OBJECT (src));
174   gst_message_unref (message);
175
176   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
177   ASSERT_OBJECT_REFCOUNT (bin, "bin", 2);
178
179   /* get and unref message 2, causing a decref on the bin */
180   fail_unless (gst_bus_poll (bus, GST_MESSAGE_STATE_CHANGED, -1)
181       == GST_MESSAGE_STATE_CHANGED, "did not get GST_MESSAGE_STATE_CHANGED");
182
183   message = gst_bus_pop (bus);
184   fail_unless (GST_MESSAGE_SRC (message) == G_OBJECT (bin));
185   gst_message_unref (message);
186
187   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
188   ASSERT_OBJECT_REFCOUNT (bin, "bin", 1);
189
190   /* clean up */
191   gst_object_unref (bin);
192 }
193
194 GST_END_TEST;
195
196 GST_START_TEST (test_message_state_changed_children)
197 {
198   GstPipeline *pipeline;
199   GstElement *src, *sink;
200   GstBus *bus;
201
202   pipeline = GST_PIPELINE (gst_pipeline_new (NULL));
203   fail_unless (pipeline != NULL, "Could not create pipeline");
204   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
205
206   src = gst_element_factory_make ("fakesrc", NULL);
207   fail_if (src == NULL, "Could not create fakesrc");
208   /* need to silence the element as the deep_notify refcounts the
209    * parents while running */
210   g_object_set (G_OBJECT (src), "silent", TRUE, NULL);
211   gst_bin_add (GST_BIN (pipeline), src);
212
213   sink = gst_element_factory_make ("fakesink", NULL);
214   /* need to silence the element as the deep_notify refcounts the
215    * parents while running */
216   g_object_set (G_OBJECT (sink), "silent", TRUE, NULL);
217   fail_if (sink == NULL, "Could not create fakesink");
218   gst_bin_add (GST_BIN (pipeline), sink);
219
220   fail_unless (gst_element_link (src, sink), "could not link src and sink");
221
222   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
223   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
224   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
225
226   bus = GST_ELEMENT_BUS (pipeline);
227
228   /* change state to READY, spawning three messages */
229   GST_DEBUG ("setting pipeline to READY");
230   fail_unless (gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_READY)
231       == GST_STATE_SUCCESS);
232
233   /* each object is referenced by a message */
234   ASSERT_OBJECT_REFCOUNT (bus, "bus", 1);
235   ASSERT_OBJECT_REFCOUNT (src, "src", 2);
236   ASSERT_OBJECT_REFCOUNT (sink, "sink", 2);
237   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 2);
238
239   pop_messages (bus, 3);
240   fail_if ((gst_bus_pop (bus)) != NULL);
241
242   ASSERT_OBJECT_REFCOUNT (bus, "bus", 1);
243   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
244   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
245   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
246
247   /* change state to PAUSED, spawning three messages */
248   GST_DEBUG ("setting pipeline to PAUSED");
249   fail_unless (gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PAUSED)
250       == GST_STATE_SUCCESS);
251
252   /* each object is referenced by a message;
253    * base_sink_chain has taken a refcount on the sink, and is blocked on
254    * preroll */
255   ASSERT_OBJECT_REFCOUNT (src, "src", 2);
256   ASSERT_OBJECT_REFCOUNT (sink, "sink", 3);
257   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 2);
258
259   pop_messages (bus, 3);
260   fail_if ((gst_bus_pop (bus)) != NULL);
261
262   ASSERT_OBJECT_REFCOUNT (bus, "bus", 1);
263   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
264   ASSERT_OBJECT_REFCOUNT (sink, "sink", 2);
265   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
266
267   /* change state to PLAYING, spawning three messages */
268   GST_DEBUG ("setting pipeline to PLAYING");
269   fail_unless (gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING)
270       == GST_STATE_SUCCESS);
271
272   /* each object is referenced by one message
273    * sink might have an extra reference if it's still blocked on preroll */
274   ASSERT_OBJECT_REFCOUNT (src, "src", 2);
275   ASSERT_OBJECT_REFCOUNT_BETWEEN (sink, "sink", 2, 3);
276   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 2);
277
278   pop_messages (bus, 3);
279   fail_if ((gst_bus_pop (bus)) != NULL);
280
281   ASSERT_OBJECT_REFCOUNT (bus, "bus", 1);
282   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
283   /* sink might have an extra reference if it's still blocked on preroll */
284   ASSERT_OBJECT_REFCOUNT_BETWEEN (sink, "sink", 1, 2);
285   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
286
287   /* go back to READY, spawning six messages */
288   GST_DEBUG ("setting pipeline to READY");
289   fail_unless (gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_READY)
290       == GST_STATE_SUCCESS);
291
292   /* each object is referenced by two messages */
293   ASSERT_OBJECT_REFCOUNT (src, "src", 3);
294   ASSERT_OBJECT_REFCOUNT (sink, "sink", 3);
295   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 3);
296
297   pop_messages (bus, 6);
298   fail_if ((gst_bus_pop (bus)) != NULL);
299
300   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
301   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
302   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
303
304   /* setting pipeline to NULL flushes the bus automatically */
305   fail_unless (gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL)
306       == GST_STATE_SUCCESS);
307
308   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
309   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
310   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
311
312   /* clean up */
313   gst_object_unref (pipeline);
314 }
315
316 GST_END_TEST;
317
318 GST_START_TEST (test_watch_for_state_change)
319 {
320   GstElement *src, *sink, *bin;
321   GstBus *bus;
322
323   bin = gst_element_factory_make ("bin", NULL);
324   fail_unless (bin != NULL, "Could not create bin");
325
326   src = gst_element_factory_make ("fakesrc", NULL);
327   fail_if (src == NULL, "Could not create fakesrc");
328   sink = gst_element_factory_make ("fakesink", NULL);
329   fail_if (sink == NULL, "Could not create fakesink");
330
331   gst_bin_add (GST_BIN (bin), sink);
332   gst_bin_add (GST_BIN (bin), src);
333
334   fail_unless (gst_element_link (src, sink), "could not link src and sink");
335
336   bus = GST_ELEMENT_BUS (bin);
337
338   /* change state, spawning two times three messages, minus one async */
339   fail_unless (gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED)
340       == GST_STATE_ASYNC);
341
342   pop_messages (bus, 5);
343
344   fail_unless (gst_bus_have_pending (bus) == FALSE,
345       "Unexpected messages on bus");
346
347   gst_bin_watch_for_state_change (GST_BIN (bin));
348
349   /* should get the bin's state change message now */
350   pop_messages (bus, 1);
351
352   fail_unless (gst_bus_have_pending (bus) == FALSE,
353       "Unexpected messages on bus");
354
355   fail_unless (gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PLAYING)
356       == GST_STATE_SUCCESS);
357
358   pop_messages (bus, 3);
359
360   /* this one might return either SUCCESS or ASYNC, likely SUCCESS */
361   gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED);
362
363   gst_bin_watch_for_state_change (GST_BIN (bin));
364
365   pop_messages (bus, 3);
366
367   fail_unless (gst_bus_have_pending (bus) == FALSE,
368       "Unexpected messages on bus");
369
370   /* setting bin to NULL flushes the bus automatically */
371   fail_unless (gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL)
372       == GST_STATE_SUCCESS);
373
374   /* clean up */
375   gst_object_unref (bin);
376 }
377
378 GST_END_TEST;
379
380 /* adding an element with linked pads to a bin unlinks the
381  * pads */
382 GST_START_TEST (test_add_linked)
383 {
384   GstElement *src, *sink;
385   GstPad *srcpad, *sinkpad;
386   GstElement *pipeline;
387
388   pipeline = gst_pipeline_new (NULL);
389   fail_unless (pipeline != NULL, "Could not create pipeline");
390
391   src = gst_element_factory_make ("fakesrc", NULL);
392   fail_if (src == NULL, "Could not create fakesrc");
393   sink = gst_element_factory_make ("fakesink", NULL);
394   fail_if (src == NULL, "Could not create fakesink");
395
396   srcpad = gst_element_get_pad (src, "src");
397   fail_unless (srcpad != NULL);
398   sinkpad = gst_element_get_pad (sink, "sink");
399   fail_unless (sinkpad != NULL);
400
401   fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK);
402
403   /* pads are linked now */
404   fail_unless (gst_pad_is_linked (srcpad));
405   fail_unless (gst_pad_is_linked (sinkpad));
406
407   /* adding element to bin voids hierarchy so pads are unlinked */
408   gst_bin_add (GST_BIN (pipeline), src);
409
410   /* check if pads really are unlinked */
411   fail_unless (!gst_pad_is_linked (srcpad));
412   fail_unless (!gst_pad_is_linked (sinkpad));
413
414   /* cannot link pads in wrong hierarchy */
415   fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_WRONG_HIERARCHY);
416
417   /* adding other element to bin as well */
418   gst_bin_add (GST_BIN (pipeline), sink);
419
420   /* now we can link again */
421   fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK);
422
423   /* check if pads really are linked */
424   fail_unless (gst_pad_is_linked (srcpad));
425   fail_unless (gst_pad_is_linked (sinkpad));
426 }
427
428 GST_END_TEST;
429
430 Suite *
431 gst_bin_suite (void)
432 {
433   Suite *s = suite_create ("GstBin");
434   TCase *tc_chain = tcase_create ("bin tests");
435
436   suite_add_tcase (s, tc_chain);
437   tcase_add_test (tc_chain, test_interface);
438   tcase_add_test (tc_chain, test_message_state_changed);
439   tcase_add_test (tc_chain, test_message_state_changed_child);
440   tcase_add_test (tc_chain, test_message_state_changed_children);
441   tcase_add_test (tc_chain, test_watch_for_state_change);
442   tcase_add_test (tc_chain, test_add_linked);
443
444   return s;
445 }
446
447 int
448 main (int argc, char **argv)
449 {
450   int nf;
451
452   Suite *s = gst_bin_suite ();
453   SRunner *sr = srunner_create (s);
454
455   gst_check_init (&argc, &argv);
456
457   srunner_run_all (sr, CK_NORMAL);
458   nf = srunner_ntests_failed (sr);
459   srunner_free (sr);
460
461   return nf;
462 }