check/gst/gstbin.c: Added checks for hierarchy consistency whan adding linked element...
[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 "../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 (message->src == GST_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 (message->src == GST_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 (src, "sink", 1);
225
226   bus = GST_ELEMENT_BUS (pipeline);
227
228   /* change state, spawning three times three messages */
229   GST_DEBUG ("setting pipeline to PLAYING");
230   fail_unless (gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING)
231       == GST_STATE_SUCCESS);
232
233   pop_messages (bus, 9);
234
235   /* this test is completely bogus as the refcount can change while running */
236 #if 0
237   ASSERT_OBJECT_REFCOUNT (bus, "bus", 1);
238   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
239   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
240   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
241 #endif
242
243   /* go back to READY, spawning six messages */
244   GST_DEBUG ("setting pipeline to READY");
245   fail_unless (gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_READY)
246       == GST_STATE_SUCCESS);
247
248   /* each object is referenced by two messages */
249   ASSERT_OBJECT_REFCOUNT (src, "src", 3);
250   ASSERT_OBJECT_REFCOUNT (sink, "sink", 3);
251   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 3);
252
253   pop_messages (bus, 6);
254
255   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
256   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
257   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
258
259   /* setting pipeline to NULL flushes the bus automatically */
260   fail_unless (gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL)
261       == GST_STATE_SUCCESS);
262
263   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
264   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
265   ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
266
267   /* clean up */
268   gst_object_unref (pipeline);
269 }
270
271 GST_END_TEST;
272
273 /* adding an element with linked pads to a bin unlinks the
274  * pads */
275 GST_START_TEST (test_add_linked)
276 {
277   GstElement *src, *sink;
278   GstPad *srcpad, *sinkpad;
279   GstElement *pipeline;
280
281   pipeline = gst_pipeline_new (NULL);
282   fail_unless (pipeline != NULL, "Could not create pipeline");
283
284   src = gst_element_factory_make ("fakesrc", NULL);
285   fail_if (src == NULL, "Could not create fakesrc");
286   sink = gst_element_factory_make ("fakesink", NULL);
287   fail_if (src == NULL, "Could not create fakesink");
288
289   srcpad = gst_element_get_pad (src, "src");
290   fail_unless (srcpad != NULL);
291   sinkpad = gst_element_get_pad (sink, "sink");
292   fail_unless (sinkpad != NULL);
293
294   fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK);
295
296   /* pads are linked now */
297   fail_unless (gst_pad_is_linked (srcpad));
298   fail_unless (gst_pad_is_linked (sinkpad));
299
300   /* adding element to bin voids hierarchy so pads are unlinked */
301   gst_bin_add (GST_BIN (pipeline), src);
302
303   /* check if pads really are unlinked */
304   fail_unless (!gst_pad_is_linked (srcpad));
305   fail_unless (!gst_pad_is_linked (sinkpad));
306
307   /* cannot link pads in wrong hierarchy */
308   fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_WRONG_HIERARCHY);
309
310   /* adding other element to bin as well */
311   gst_bin_add (GST_BIN (pipeline), sink);
312
313   /* now we can link again */
314   fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK);
315
316   /* check if pads really are linked */
317   fail_unless (gst_pad_is_linked (srcpad));
318   fail_unless (gst_pad_is_linked (sinkpad));
319 }
320
321 GST_END_TEST;
322
323 Suite *
324 gst_bin_suite (void)
325 {
326   Suite *s = suite_create ("GstBin");
327   TCase *tc_chain = tcase_create ("bin tests");
328
329   suite_add_tcase (s, tc_chain);
330   tcase_add_test (tc_chain, test_interface);
331   tcase_add_test (tc_chain, test_message_state_changed);
332   tcase_add_test (tc_chain, test_message_state_changed_child);
333   tcase_add_test (tc_chain, test_message_state_changed_children);
334   tcase_add_test (tc_chain, test_add_linked);
335
336   return s;
337 }
338
339 int
340 main (int argc, char **argv)
341 {
342   int nf;
343
344   Suite *s = gst_bin_suite ();
345   SRunner *sr = srunner_create (s);
346
347   gst_check_init (&argc, &argv);
348
349   srunner_run_all (sr, CK_NORMAL);
350   nf = srunner_ntests_failed (sr);
351   srunner_free (sr);
352
353   return nf;
354 }