add a check for a ghostpad that doesn't have a target being linked
[platform/upstream/gstreamer.git] / check / gst / gstghostpad.c
1 /* GStreamer
2  * Copyright (C) 2005 Wim Taymans <wim@fluendo.com>
3  *
4  * gstghostpad.c: Unit test for GstGhostPad
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 #include <gst/check/gstcheck.h>
23
24 static void
25 assert_gstrefcount (gpointer p, gint i)
26 {
27   if (GST_OBJECT_REFCOUNT_VALUE (p) != i)
28     g_critical ("Expected refcount %d for %s, got %d", i, GST_OBJECT_NAME (p),
29         GST_OBJECT_REFCOUNT_VALUE (p));
30 }
31
32 /* test if removing a bin also cleans up the ghostpads
33  */
34 GST_START_TEST (test_remove1)
35 {
36   GstElement *b1, *b2, *src, *sink;
37   GstPad *srcpad, *sinkpad;
38   GstPadLinkReturn ret;
39
40   b1 = gst_element_factory_make ("pipeline", NULL);
41   b2 = gst_element_factory_make ("bin", NULL);
42   src = gst_element_factory_make ("fakesrc", NULL);
43   sink = gst_element_factory_make ("fakesink", NULL);
44
45   fail_unless (gst_bin_add (GST_BIN (b2), sink));
46   fail_unless (gst_bin_add (GST_BIN (b1), src));
47   fail_unless (gst_bin_add (GST_BIN (b1), b2));
48
49   sinkpad = gst_element_get_pad (sink, "sink");
50   gst_element_add_pad (b2, gst_ghost_pad_new ("sink", sinkpad));
51   gst_object_unref (sinkpad);
52
53   srcpad = gst_element_get_pad (src, "src");
54   /* get the ghostpad */
55   sinkpad = gst_element_get_pad (b2, "sink");
56
57   ret = gst_pad_link (srcpad, sinkpad);
58   fail_unless (ret == GST_PAD_LINK_OK);
59   gst_object_unref (srcpad);
60   gst_object_unref (sinkpad);
61
62   /* now remove the bin with the ghostpad, b2 is disposed
63    * now. */
64   gst_bin_remove (GST_BIN (b1), b2);
65
66   srcpad = gst_element_get_pad (src, "src");
67   /* pad cannot be linked now */
68   fail_if (gst_pad_is_linked (srcpad));
69 }
70
71 GST_END_TEST;
72
73 /* test if removing a bin also cleans up the ghostpads
74  */
75 GST_START_TEST (test_remove2)
76 {
77   GstElement *b1, *b2, *src, *sink;
78   GstPad *srcpad, *sinkpad;
79   GstPadLinkReturn ret;
80
81   b1 = gst_element_factory_make ("pipeline", NULL);
82   b2 = gst_element_factory_make ("bin", NULL);
83   src = gst_element_factory_make ("fakesrc", NULL);
84   sink = gst_element_factory_make ("fakesink", NULL);
85
86   fail_unless (gst_bin_add (GST_BIN (b2), sink));
87   fail_unless (gst_bin_add (GST_BIN (b1), src));
88   fail_unless (gst_bin_add (GST_BIN (b1), b2));
89
90   sinkpad = gst_element_get_pad (sink, "sink");
91   gst_element_add_pad (b2, gst_ghost_pad_new ("sink", sinkpad));
92   gst_object_unref (sinkpad);
93
94   srcpad = gst_element_get_pad (src, "src");
95   /* get the ghostpad */
96   sinkpad = gst_element_get_pad (b2, "sink");
97
98   ret = gst_pad_link (srcpad, sinkpad);
99   fail_unless (ret == GST_PAD_LINK_OK);
100   gst_object_unref (srcpad);
101   gst_object_unref (sinkpad);
102
103   /* now remove the sink from the bin */
104   gst_bin_remove (GST_BIN (b2), sink);
105
106   srcpad = gst_element_get_pad (src, "src");
107   /* pad is still linked to ghostpad */
108   fail_if (!gst_pad_is_linked (srcpad));
109 }
110
111 GST_END_TEST;
112
113 #if 0
114 /* test if a ghost pad without a target can be linked
115  *
116  */
117 GST_START_TEST (test_ghost_pad_notarget)
118 {
119   GstElement *b1, *b2, *sink;
120   GstPad *srcpad, *sinkpad;
121   GstPadLinkReturn ret;
122
123   b1 = gst_element_factory_make ("pipeline", NULL);
124   b2 = gst_element_factory_make ("bin", NULL);
125   sink = gst_element_factory_make ("fakesink", NULL);
126
127   fail_unless (gst_bin_add (GST_BIN (b1), sink));
128   fail_unless (gst_bin_add (GST_BIN (b1), b2));
129
130   srcpad = gst_ghost_pad_new_notarget ("src", GST_PAD_SRC);
131   fail_unless (srcpad != NULL);
132   sinkpad = gst_element_get_pad (sink, "sink");
133   fail_unless (sinkpad != NULL);
134
135   ret = gst_pad_link (srcpad, sinkpad);
136   fail_unless (ret == GST_PAD_LINK_OK);
137 }
138
139 GST_END_TEST;
140 #endif
141
142 /* test if linking fails over different bins using a pipeline
143  * like this:
144  *
145  * fakesrc num_buffers=10 ! ( fakesink )
146  *
147  */
148 GST_START_TEST (test_link)
149 {
150   GstElement *b1, *b2, *src, *sink;
151   GstPad *srcpad, *sinkpad, *gpad;
152   GstPadLinkReturn ret;
153
154   b1 = gst_element_factory_make ("pipeline", NULL);
155   b2 = gst_element_factory_make ("bin", NULL);
156   src = gst_element_factory_make ("fakesrc", NULL);
157   sink = gst_element_factory_make ("fakesink", NULL);
158
159   fail_unless (gst_bin_add (GST_BIN (b2), sink));
160   fail_unless (gst_bin_add (GST_BIN (b1), src));
161   fail_unless (gst_bin_add (GST_BIN (b1), b2));
162
163   srcpad = gst_element_get_pad (src, "src");
164   fail_unless (srcpad != NULL);
165   sinkpad = gst_element_get_pad (sink, "sink");
166   fail_unless (sinkpad != NULL);
167
168   /* linking in different hierarchies should fail */
169   ret = gst_pad_link (srcpad, sinkpad);
170   fail_unless (ret == GST_PAD_LINK_WRONG_HIERARCHY);
171
172   /* now setup a ghostpad */
173   gpad = gst_ghost_pad_new ("sink", sinkpad);
174   gst_object_unref (sinkpad);
175   /* need to ref as _add_pad takes ownership */
176   gst_object_ref (gpad);
177   gst_element_add_pad (b2, gpad);
178
179   /* our new sinkpad */
180   sinkpad = gpad;
181
182   /* and linking should work now */
183   ret = gst_pad_link (srcpad, sinkpad);
184   fail_unless (ret == GST_PAD_LINK_OK);
185 }
186
187 GST_END_TEST;
188
189 /* test if ghostpads are created automagically when using
190  * gst_element_link_pads.
191  *
192  * fakesrc num_buffers=10 ! ( identity ) ! fakesink
193  */
194 GST_START_TEST (test_ghost_pads)
195 {
196   GstElement *b1, *b2, *src, *i1, *sink;
197   GstPad *gsink, *gsrc, *gisrc, *gisink, *isink, *isrc, *fsrc, *fsink;
198
199   b1 = gst_element_factory_make ("pipeline", NULL);
200   b2 = gst_element_factory_make ("bin", NULL);
201   src = gst_element_factory_make ("fakesrc", NULL);
202   g_object_set (src, "num-buffers", (int) 10, NULL);
203   i1 = gst_element_factory_make ("identity", NULL);
204   sink = gst_element_factory_make ("fakesink", NULL);
205
206   fail_unless (gst_bin_add (GST_BIN (b2), i1));
207   fail_unless (gst_bin_add (GST_BIN (b1), src));
208   fail_unless (gst_bin_add (GST_BIN (b1), b2));
209   fail_unless (gst_bin_add (GST_BIN (b1), sink));
210   fail_unless (gst_element_link_pads (src, NULL, i1, NULL));
211   fail_unless (gst_element_link_pads (i1, NULL, sink, NULL));
212   GST_LOCK (b2);
213   fail_unless (b2->numsinkpads == 1);
214   fail_unless (GST_IS_GHOST_PAD (b2->sinkpads->data));
215   fail_unless (b2->numsrcpads == 1);
216   fail_unless (GST_IS_GHOST_PAD (b2->srcpads->data));
217   GST_UNLOCK (b2);
218
219   fsrc = gst_element_get_pad (src, "src");
220   fail_unless (fsrc != NULL);
221   gsink = GST_PAD (gst_object_ref (b2->sinkpads->data));
222   fail_unless (gsink != NULL);
223   gsrc = GST_PAD (gst_object_ref (b2->srcpads->data));
224   fail_unless (gsrc != NULL);
225   fsink = gst_element_get_pad (sink, "sink");
226   fail_unless (fsink != NULL);
227
228   isink = gst_element_get_pad (i1, "sink");
229   fail_unless (isink != NULL);
230   isrc = gst_element_get_pad (i1, "src");
231   fail_unless (isrc != NULL);
232   gisrc = gst_pad_get_peer (isink);
233   fail_unless (gisrc != NULL);
234   gisink = gst_pad_get_peer (isrc);
235   fail_unless (gisink != NULL);
236
237   /* all objects above have one refcount owned by us as well */
238
239   assert_gstrefcount (fsrc, 3); /* parent and gisrc */
240   assert_gstrefcount (gsink, 2);        /* parent */
241   assert_gstrefcount (gsrc, 2); /* parent */
242   assert_gstrefcount (fsink, 3);        /* parent and gisink */
243
244   assert_gstrefcount (gisrc, 2);        /* parent */
245   assert_gstrefcount (isink, 3);        /* parent and gsink */
246   assert_gstrefcount (gisink, 2);       /* parent */
247   assert_gstrefcount (isrc, 3); /* parent and gsrc */
248
249   fail_unless (gst_element_set_state (b1,
250           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS);
251
252   fail_unless (gst_element_set_state (b1,
253           GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS);
254
255   gst_object_unref (b1);
256   /* unreffing the bin will unref all elements, which will unlink and unparent
257    * all pads */
258
259   assert_gstrefcount (fsrc, 2); /* gisrc */
260   assert_gstrefcount (gsink, 1);
261   assert_gstrefcount (gsrc, 1);
262   assert_gstrefcount (fsink, 2);        /* gisink */
263
264   assert_gstrefcount (gisrc, 1);        /* gsink */
265   assert_gstrefcount (isink, 2);        /* gsink */
266   assert_gstrefcount (gisink, 1);       /* gsrc */
267   assert_gstrefcount (isrc, 2); /* gsrc */
268
269   gst_object_unref (gsink);
270   assert_gstrefcount (isink, 1);
271   assert_gstrefcount (gisrc, 1);
272   assert_gstrefcount (fsrc, 2); /* gisrc */
273   gst_object_unref (gisrc);
274   assert_gstrefcount (fsrc, 1);
275
276   gst_object_unref (gsrc);
277   assert_gstrefcount (isrc, 1);
278   assert_gstrefcount (gisink, 1);
279   assert_gstrefcount (fsink, 2);        /* gisrc */
280   gst_object_unref (gisink);
281   assert_gstrefcount (fsink, 1);
282
283   gst_object_unref (fsrc);
284   gst_object_unref (isrc);
285   gst_object_unref (isink);
286   gst_object_unref (fsink);
287 }
288
289 GST_END_TEST;
290
291 Suite *
292 gst_ghost_pad_suite (void)
293 {
294   Suite *s = suite_create ("GstGhostPad");
295   TCase *tc_chain = tcase_create ("ghost pad tests");
296
297   suite_add_tcase (s, tc_chain);
298   tcase_add_test (tc_chain, test_remove1);
299   tcase_add_test (tc_chain, test_remove2);
300   tcase_add_test (tc_chain, test_link);
301   tcase_add_test (tc_chain, test_ghost_pads);
302 /*  tcase_add_test (tc_chain, test_ghost_pad_notarget); */
303
304   return s;
305 }
306
307 int
308 main (int argc, char **argv)
309 {
310   int nf;
311
312   Suite *s = gst_ghost_pad_suite ();
313   SRunner *sr = srunner_create (s);
314
315   gst_check_init (&argc, &argv);
316
317   srunner_run_all (sr, CK_NORMAL);
318   nf = srunner_ntests_failed (sr);
319   srunner_free (sr);
320
321   return nf;
322 }