gst/gstpad.*: Added _CUSTOM error and success GstFlowReturn that can be used be eleme...
[platform/upstream/gstreamer.git] / tests / check / gst / gstpad.c
1 /* GStreamer
2  * Copyright (C) <2005> Thomas Vander Stichele <thomas at apestaart dot org>
3  *
4  * gstpad.c: Unit test for GstPad
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 GST_START_TEST (test_link)
25 {
26   GstPad *src, *sink;
27   GstPadTemplate *srct;
28
29   GstPadLinkReturn ret;
30   gchar *name;
31
32   src = gst_pad_new ("source", GST_PAD_SRC);
33   fail_if (src == NULL);
34   ASSERT_OBJECT_REFCOUNT (src, "source pad", 1);
35
36   name = gst_pad_get_name (src);
37   fail_unless (strcmp (name, "source") == 0);
38   ASSERT_OBJECT_REFCOUNT (src, "source pad", 1);
39   g_free (name);
40
41   sink = gst_pad_new ("sink", GST_PAD_SINK);
42   fail_if (sink == NULL);
43
44   /* linking without templates or caps should fail */
45   ret = gst_pad_link (src, sink);
46   ASSERT_OBJECT_REFCOUNT (src, "source pad", 1);
47   ASSERT_OBJECT_REFCOUNT (sink, "sink pad", 1);
48   fail_unless (ret == GST_PAD_LINK_NOFORMAT);
49
50   ASSERT_CRITICAL (gst_pad_get_pad_template (NULL));
51
52   srct = gst_pad_get_pad_template (src);
53   fail_unless (srct == NULL);
54   ASSERT_OBJECT_REFCOUNT (src, "source pad", 1);
55
56   /* clean up */
57   ASSERT_OBJECT_REFCOUNT (src, "source pad", 1);
58   gst_object_unref (src);
59   gst_object_unref (sink);
60 }
61
62 GST_END_TEST;
63
64 /* threaded link/unlink */
65 /* use globals */
66 GstPad *src, *sink;
67
68 void
69 thread_link_unlink (gpointer data)
70 {
71   THREAD_START ();
72
73   while (THREAD_TEST_RUNNING ()) {
74     gst_pad_link (src, sink);
75     gst_pad_unlink (src, sink);
76     THREAD_SWITCH ();
77   }
78 }
79
80 GST_START_TEST (test_link_unlink_threaded)
81 {
82   GstCaps *caps;
83   int i;
84
85   src = gst_pad_new ("source", GST_PAD_SRC);
86   fail_if (src == NULL);
87   sink = gst_pad_new ("sink", GST_PAD_SINK);
88   fail_if (sink == NULL);
89
90   caps = gst_caps_from_string ("foo/bar");
91   gst_pad_set_caps (src, caps);
92   gst_pad_set_caps (sink, caps);
93
94   MAIN_START_THREADS (5, thread_link_unlink, NULL);
95   for (i = 0; i < 1000; ++i) {
96     gst_pad_is_linked (src);
97     gst_pad_is_linked (sink);
98     THREAD_SWITCH ();
99   }
100   MAIN_STOP_THREADS ();
101 }
102
103 GST_END_TEST;
104
105 GST_START_TEST (test_refcount)
106 {
107   GstPad *src, *sink;
108   GstCaps *caps;
109   GstPadLinkReturn plr;
110
111   sink = gst_pad_new ("sink", GST_PAD_SINK);
112   fail_if (sink == NULL);
113
114   src = gst_pad_new ("src", GST_PAD_SRC);
115   fail_if (src == NULL);
116
117   caps = gst_caps_from_string ("foo/bar");
118   /* one for me */
119   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
120
121   gst_pad_set_caps (src, caps);
122   gst_pad_set_caps (sink, caps);
123   /* one for me and one for each set_caps */
124   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
125
126   plr = gst_pad_link (src, sink);
127   fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
128   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
129
130   gst_pad_unlink (src, sink);
131   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
132
133   /* cleanup */
134   gst_object_unref (src);
135   gst_object_unref (sink);
136   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
137
138   gst_caps_unref (caps);
139 }
140
141 GST_END_TEST;
142
143 GST_START_TEST (test_get_allowed_caps)
144 {
145   GstPad *src, *sink;
146   GstCaps *caps, *gotcaps;
147   GstBuffer *buffer;
148   GstPadLinkReturn plr;
149
150   ASSERT_CRITICAL (gst_pad_get_allowed_caps (NULL));
151
152   buffer = gst_buffer_new ();
153   ASSERT_CRITICAL (gst_pad_get_allowed_caps ((GstPad *) buffer));
154   gst_buffer_unref (buffer);
155
156   sink = gst_pad_new ("sink", GST_PAD_SINK);
157   ASSERT_CRITICAL (gst_pad_get_allowed_caps (sink));
158
159   src = gst_pad_new ("src", GST_PAD_SRC);
160   fail_if (src == NULL);
161   caps = gst_pad_get_allowed_caps (src);
162   fail_unless (caps == NULL);
163
164   caps = gst_caps_from_string ("foo/bar");
165
166   gst_pad_set_caps (src, caps);
167   gst_pad_set_caps (sink, caps);
168   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
169
170   plr = gst_pad_link (src, sink);
171   fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
172
173   gotcaps = gst_pad_get_allowed_caps (src);
174   fail_if (gotcaps == NULL);
175   fail_unless (gst_caps_is_equal (gotcaps, caps));
176
177   ASSERT_CAPS_REFCOUNT (gotcaps, "gotcaps", 1);
178   gst_caps_unref (gotcaps);
179
180   gst_pad_unlink (src, sink);
181
182   /* cleanup */
183   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
184   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
185   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
186
187   gst_object_unref (src);
188   gst_object_unref (sink);
189
190   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
191   gst_caps_unref (caps);
192 }
193
194 GST_END_TEST;
195
196 static gboolean
197 name_is_valid (const gchar * name, GstPadPresence presence)
198 {
199   GstPadTemplate *new;
200
201   new = gst_pad_template_new (name, GST_PAD_SRC, presence, GST_CAPS_ANY);
202   if (new) {
203     gst_object_unref (GST_OBJECT (new));
204     return TRUE;
205   }
206   return FALSE;
207 }
208
209 GST_START_TEST (test_name_is_valid)
210 {
211   gboolean result = FALSE;
212
213   fail_unless (name_is_valid ("src", GST_PAD_ALWAYS));
214   ASSERT_WARNING (name_is_valid ("src%", GST_PAD_ALWAYS));
215   ASSERT_WARNING (result = name_is_valid ("src%d", GST_PAD_ALWAYS));
216   fail_if (result);
217
218   fail_unless (name_is_valid ("src", GST_PAD_REQUEST));
219   ASSERT_WARNING (name_is_valid ("src%s%s", GST_PAD_REQUEST));
220   ASSERT_WARNING (name_is_valid ("src%c", GST_PAD_REQUEST));
221   ASSERT_WARNING (name_is_valid ("src%", GST_PAD_REQUEST));
222   ASSERT_WARNING (name_is_valid ("src%dsrc", GST_PAD_REQUEST));
223
224   fail_unless (name_is_valid ("src", GST_PAD_SOMETIMES));
225   fail_unless (name_is_valid ("src%c", GST_PAD_SOMETIMES));
226 }
227
228 GST_END_TEST;
229
230 static gboolean
231 _probe_handler (GstPad * pad, GstBuffer * buffer, gpointer userdata)
232 {
233   gint ret = GPOINTER_TO_INT (userdata);
234
235   if (ret == 1)
236     return TRUE;
237   return FALSE;
238 }
239
240 GST_START_TEST (test_push_unlinked)
241 {
242   GstPad *src;
243   GstCaps *caps;
244   GstBuffer *buffer;
245   gulong id;
246
247   src = gst_pad_new ("src", GST_PAD_SRC);
248   fail_if (src == NULL);
249   caps = gst_pad_get_allowed_caps (src);
250   fail_unless (caps == NULL);
251
252   caps = gst_caps_from_string ("foo/bar");
253
254   gst_pad_set_caps (src, caps);
255   ASSERT_CAPS_REFCOUNT (caps, "caps", 2);
256
257   /* pushing on an unlinked pad will drop the buffer */
258   buffer = gst_buffer_new ();
259   gst_buffer_ref (buffer);
260   fail_unless (gst_pad_push (src, buffer) == GST_FLOW_NOT_LINKED);
261   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
262   gst_buffer_unref (buffer);
263
264   /* adding a probe that returns FALSE will drop the buffer without trying
265    * to chain */
266   id = gst_pad_add_buffer_probe (src, (GCallback) _probe_handler,
267       GINT_TO_POINTER (0));
268   buffer = gst_buffer_new ();
269   gst_buffer_ref (buffer);
270   fail_unless (gst_pad_push (src, buffer) == GST_FLOW_OK);
271   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
272   gst_buffer_unref (buffer);
273   gst_pad_remove_buffer_probe (src, id);
274
275   /* adding a probe that returns TRUE will still chain the buffer,
276    * and hence drop because pad is unlinked */
277   id = gst_pad_add_buffer_probe (src, (GCallback) _probe_handler,
278       GINT_TO_POINTER (1));
279   buffer = gst_buffer_new ();
280   gst_buffer_ref (buffer);
281   fail_unless (gst_pad_push (src, buffer) == GST_FLOW_NOT_LINKED);
282   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
283   gst_buffer_unref (buffer);
284   gst_pad_remove_buffer_probe (src, id);
285
286
287   /* cleanup */
288   ASSERT_CAPS_REFCOUNT (caps, "caps", 2);
289   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
290
291   gst_object_unref (src);
292
293   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
294   gst_caps_unref (caps);
295 }
296
297 GST_END_TEST;
298
299 GST_START_TEST (test_push_linked)
300 {
301   GstPad *src, *sink;
302   GstPadLinkReturn plr;
303   GstCaps *caps;
304   GstBuffer *buffer;
305   ulong id;
306
307   /* setup */
308   sink = gst_pad_new ("sink", GST_PAD_SINK);
309   fail_if (sink == NULL);
310   gst_pad_set_chain_function (sink, gst_check_chain_func);
311
312   src = gst_pad_new ("src", GST_PAD_SRC);
313   fail_if (src == NULL);
314
315   caps = gst_caps_from_string ("foo/bar");
316   /* one for me */
317   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
318
319   gst_pad_set_caps (src, caps);
320   gst_pad_set_caps (sink, caps);
321   /* one for me and one for each set_caps */
322   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
323
324   plr = gst_pad_link (src, sink);
325   fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
326   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
327
328   /* test */
329   /* pushing on a linked pad will drop the ref to the buffer */
330   buffer = gst_buffer_new ();
331   gst_buffer_ref (buffer);
332   fail_unless (gst_pad_push (src, buffer) == GST_FLOW_OK);
333   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 2);
334   gst_buffer_unref (buffer);
335   fail_unless_equals_int (g_list_length (buffers), 1);
336   buffer = GST_BUFFER (buffers->data);
337   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
338   gst_buffer_unref (buffer);
339   g_list_free (buffers);
340   buffers = NULL;
341
342   /* adding a probe that returns FALSE will drop the buffer without trying
343    * to chain */
344   id = gst_pad_add_buffer_probe (src, (GCallback) _probe_handler,
345       GINT_TO_POINTER (0));
346   buffer = gst_buffer_new ();
347   gst_buffer_ref (buffer);
348   fail_unless (gst_pad_push (src, buffer) == GST_FLOW_OK);
349   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
350   gst_buffer_unref (buffer);
351   gst_pad_remove_buffer_probe (src, id);
352   fail_unless_equals_int (g_list_length (buffers), 0);
353
354   /* adding a probe that returns TRUE will still chain the buffer */
355   id = gst_pad_add_buffer_probe (src, (GCallback) _probe_handler,
356       GINT_TO_POINTER (1));
357   buffer = gst_buffer_new ();
358   gst_buffer_ref (buffer);
359   fail_unless (gst_pad_push (src, buffer) == GST_FLOW_OK);
360   gst_pad_remove_buffer_probe (src, id);
361
362   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 2);
363   gst_buffer_unref (buffer);
364   fail_unless_equals_int (g_list_length (buffers), 1);
365   buffer = GST_BUFFER (buffers->data);
366   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
367   gst_buffer_unref (buffer);
368   g_list_free (buffers);
369   buffers = NULL;
370
371   /* teardown */
372   gst_pad_unlink (src, sink);
373   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
374   gst_object_unref (src);
375   gst_object_unref (sink);
376   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
377
378   gst_caps_unref (caps);
379 }
380
381 GST_END_TEST;
382
383 GST_START_TEST (test_flowreturn)
384 {
385   GstFlowReturn ret;
386   GQuark quark;
387
388   /* test some of the macros */
389   ret = GST_FLOW_UNEXPECTED;
390   fail_unless (GST_FLOW_IS_FATAL (ret));
391   fail_if (GST_FLOW_IS_SUCCESS (ret));
392   fail_if (strcmp (gst_flow_get_name (ret), "unexpected"));
393   quark = gst_flow_to_quark (ret);
394   fail_if (strcmp (g_quark_to_string (quark), "unexpected"));
395
396   ret = GST_FLOW_RESEND;
397   fail_if (GST_FLOW_IS_FATAL (ret));
398   fail_unless (GST_FLOW_IS_SUCCESS (ret));
399   fail_if (strcmp (gst_flow_get_name (ret), "resend"));
400   quark = gst_flow_to_quark (ret);
401   fail_if (strcmp (g_quark_to_string (quark), "resend"));
402
403   /* custom returns */
404   ret = GST_FLOW_CUSTOM_SUCCESS;
405   fail_if (GST_FLOW_IS_FATAL (ret));
406   fail_unless (GST_FLOW_IS_SUCCESS (ret));
407   fail_if (strcmp (gst_flow_get_name (ret), "custom-success"));
408   quark = gst_flow_to_quark (ret);
409   fail_if (strcmp (g_quark_to_string (quark), "custom-success"));
410
411   ret = GST_FLOW_CUSTOM_ERROR;
412   fail_unless (GST_FLOW_IS_FATAL (ret));
413   fail_if (GST_FLOW_IS_SUCCESS (ret));
414   fail_if (strcmp (gst_flow_get_name (ret), "custom-error"));
415   quark = gst_flow_to_quark (ret);
416   fail_if (strcmp (g_quark_to_string (quark), "custom-error"));
417
418   /* custom returns clamping */
419   ret = GST_FLOW_CUSTOM_SUCCESS + 2;
420   fail_if (GST_FLOW_IS_FATAL (ret));
421   fail_unless (GST_FLOW_IS_SUCCESS (ret));
422   fail_if (strcmp (gst_flow_get_name (ret), "custom-success"));
423   quark = gst_flow_to_quark (ret);
424   fail_if (strcmp (g_quark_to_string (quark), "custom-success"));
425
426   ret = GST_FLOW_CUSTOM_ERROR - 2;
427   fail_unless (GST_FLOW_IS_FATAL (ret));
428   fail_if (GST_FLOW_IS_SUCCESS (ret));
429   fail_if (strcmp (gst_flow_get_name (ret), "custom-error"));
430   quark = gst_flow_to_quark (ret);
431   fail_if (strcmp (g_quark_to_string (quark), "custom-error"));
432
433   /* unknown values */
434   ret = GST_FLOW_CUSTOM_ERROR + 2;
435   fail_unless (GST_FLOW_IS_FATAL (ret));
436   fail_if (GST_FLOW_IS_SUCCESS (ret));
437   fail_if (strcmp (gst_flow_get_name (ret), "unknown"));
438   quark = gst_flow_to_quark (ret);
439   fail_unless (quark == 0);
440
441 }
442
443 GST_END_TEST;
444
445 Suite *
446 gst_pad_suite (void)
447 {
448   Suite *s = suite_create ("GstPad");
449   TCase *tc_chain = tcase_create ("general");
450
451   /* turn off timeout */
452   tcase_set_timeout (tc_chain, 60);
453
454   suite_add_tcase (s, tc_chain);
455   tcase_add_test (tc_chain, test_link);
456   tcase_add_test (tc_chain, test_refcount);
457   tcase_add_test (tc_chain, test_get_allowed_caps);
458   tcase_add_test (tc_chain, test_link_unlink_threaded);
459   tcase_add_test (tc_chain, test_name_is_valid);
460   tcase_add_test (tc_chain, test_push_unlinked);
461   tcase_add_test (tc_chain, test_push_linked);
462   tcase_add_test (tc_chain, test_flowreturn);
463
464   return s;
465 }
466
467 int
468 main (int argc, char **argv)
469 {
470   int nf;
471
472   Suite *s = gst_pad_suite ();
473   SRunner *sr = srunner_create (s);
474
475   gst_check_init (&argc, &argv);
476
477   srunner_run_all (sr, CK_NORMAL);
478   nf = srunner_ntests_failed (sr);
479   srunner_free (sr);
480
481   return nf;
482 }