2 * Copyright (C) <2005> Thomas Vander Stichele <thomas at apestaart dot org>
4 * gstpad.c: Unit test for GstPad
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.
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.
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.
22 #include <gst/check/gstcheck.h>
24 GST_START_TEST (test_link)
32 src = gst_pad_new ("source", GST_PAD_SRC);
33 fail_if (src == NULL);
34 ASSERT_OBJECT_REFCOUNT (src, "source pad", 1);
36 name = gst_pad_get_name (src);
37 fail_unless (strcmp (name, "source") == 0);
38 ASSERT_OBJECT_REFCOUNT (src, "source pad", 1);
41 sink = gst_pad_new ("sink", GST_PAD_SINK);
42 fail_if (sink == NULL);
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);
50 ASSERT_CRITICAL (gst_pad_get_pad_template (NULL));
52 srct = gst_pad_get_pad_template (src);
53 fail_unless (srct == NULL);
54 ASSERT_OBJECT_REFCOUNT (src, "source pad", 1);
57 ASSERT_OBJECT_REFCOUNT (src, "source pad", 1);
58 gst_object_unref (src);
59 gst_object_unref (sink);
64 /* threaded link/unlink */
69 thread_link_unlink (gpointer data)
73 while (THREAD_TEST_RUNNING ()) {
74 gst_pad_link (src, sink);
75 gst_pad_unlink (src, sink);
80 GST_START_TEST (test_link_unlink_threaded)
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);
90 caps = gst_caps_from_string ("foo/bar");
91 gst_pad_set_caps (src, caps);
92 gst_pad_set_caps (sink, caps);
93 ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
95 MAIN_START_THREADS (5, thread_link_unlink, NULL);
96 for (i = 0; i < 1000; ++i) {
97 gst_pad_is_linked (src);
98 gst_pad_is_linked (sink);
101 MAIN_STOP_THREADS ();
103 ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
104 gst_caps_unref (caps);
106 ASSERT_CAPS_REFCOUNT (caps, "caps", 2);
107 gst_object_unref (src);
108 gst_object_unref (sink);
113 GST_START_TEST (test_refcount)
117 GstPadLinkReturn plr;
119 sink = gst_pad_new ("sink", GST_PAD_SINK);
120 fail_if (sink == NULL);
122 src = gst_pad_new ("src", GST_PAD_SRC);
123 fail_if (src == NULL);
125 caps = gst_caps_from_string ("foo/bar");
127 ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
129 gst_pad_set_caps (src, caps);
130 gst_pad_set_caps (sink, caps);
131 /* one for me and one for each set_caps */
132 ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
134 plr = gst_pad_link (src, sink);
135 fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
136 ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
138 gst_pad_unlink (src, sink);
139 ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
142 gst_object_unref (src);
143 gst_object_unref (sink);
144 ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
146 gst_caps_unref (caps);
151 GST_START_TEST (test_get_allowed_caps)
154 GstCaps *caps, *gotcaps;
156 GstPadLinkReturn plr;
158 ASSERT_CRITICAL (gst_pad_get_allowed_caps (NULL));
160 buffer = gst_buffer_new ();
161 ASSERT_CRITICAL (gst_pad_get_allowed_caps ((GstPad *) buffer));
162 gst_buffer_unref (buffer);
164 sink = gst_pad_new ("sink", GST_PAD_SINK);
165 ASSERT_CRITICAL (gst_pad_get_allowed_caps (sink));
167 src = gst_pad_new ("src", GST_PAD_SRC);
168 fail_if (src == NULL);
169 caps = gst_pad_get_allowed_caps (src);
170 fail_unless (caps == NULL);
172 caps = gst_caps_from_string ("foo/bar");
174 gst_pad_set_caps (src, caps);
175 gst_pad_set_caps (sink, caps);
176 ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
178 plr = gst_pad_link (src, sink);
179 fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
181 gotcaps = gst_pad_get_allowed_caps (src);
182 fail_if (gotcaps == NULL);
183 fail_unless (gst_caps_is_equal (gotcaps, caps));
185 ASSERT_CAPS_REFCOUNT (gotcaps, "gotcaps", 1);
186 gst_caps_unref (gotcaps);
188 gst_pad_unlink (src, sink);
191 ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
192 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
193 ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
195 gst_object_unref (src);
196 gst_object_unref (sink);
198 ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
199 gst_caps_unref (caps);
205 name_is_valid (const gchar * name, GstPadPresence presence)
209 new = gst_pad_template_new (name, GST_PAD_SRC, presence, GST_CAPS_ANY);
211 gst_object_unref (GST_OBJECT (new));
217 GST_START_TEST (test_name_is_valid)
219 gboolean result = FALSE;
221 fail_unless (name_is_valid ("src", GST_PAD_ALWAYS));
222 ASSERT_WARNING (name_is_valid ("src%", GST_PAD_ALWAYS));
223 ASSERT_WARNING (result = name_is_valid ("src%d", GST_PAD_ALWAYS));
226 fail_unless (name_is_valid ("src", GST_PAD_REQUEST));
227 ASSERT_WARNING (name_is_valid ("src%s%s", GST_PAD_REQUEST));
228 ASSERT_WARNING (name_is_valid ("src%c", GST_PAD_REQUEST));
229 ASSERT_WARNING (name_is_valid ("src%", GST_PAD_REQUEST));
230 ASSERT_WARNING (name_is_valid ("src%dsrc", GST_PAD_REQUEST));
232 fail_unless (name_is_valid ("src", GST_PAD_SOMETIMES));
233 fail_unless (name_is_valid ("src%c", GST_PAD_SOMETIMES));
239 _probe_handler (GstPad * pad, GstBuffer * buffer, gpointer userdata)
241 gint ret = GPOINTER_TO_INT (userdata);
248 GST_START_TEST (test_push_unlinked)
255 src = gst_pad_new ("src", GST_PAD_SRC);
256 fail_if (src == NULL);
257 caps = gst_pad_get_allowed_caps (src);
258 fail_unless (caps == NULL);
260 caps = gst_caps_from_string ("foo/bar");
262 gst_pad_set_caps (src, caps);
263 ASSERT_CAPS_REFCOUNT (caps, "caps", 2);
265 /* pushing on an unlinked pad will drop the buffer */
266 buffer = gst_buffer_new ();
267 gst_buffer_ref (buffer);
268 fail_unless (gst_pad_push (src, buffer) == GST_FLOW_NOT_LINKED);
269 ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
270 gst_buffer_unref (buffer);
272 /* adding a probe that returns FALSE will drop the buffer without trying
274 id = gst_pad_add_buffer_probe (src, (GCallback) _probe_handler,
275 GINT_TO_POINTER (0));
276 buffer = gst_buffer_new ();
277 gst_buffer_ref (buffer);
278 fail_unless (gst_pad_push (src, buffer) == GST_FLOW_OK);
279 ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
280 gst_buffer_unref (buffer);
281 gst_pad_remove_buffer_probe (src, id);
283 /* adding a probe that returns TRUE will still chain the buffer,
284 * and hence drop because pad is unlinked */
285 id = gst_pad_add_buffer_probe (src, (GCallback) _probe_handler,
286 GINT_TO_POINTER (1));
287 buffer = gst_buffer_new ();
288 gst_buffer_ref (buffer);
289 fail_unless (gst_pad_push (src, buffer) == GST_FLOW_NOT_LINKED);
290 ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
291 gst_buffer_unref (buffer);
292 gst_pad_remove_buffer_probe (src, id);
296 ASSERT_CAPS_REFCOUNT (caps, "caps", 2);
297 ASSERT_OBJECT_REFCOUNT (src, "src", 1);
299 gst_object_unref (src);
301 ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
302 gst_caps_unref (caps);
307 GST_START_TEST (test_push_linked)
310 GstPadLinkReturn plr;
316 sink = gst_pad_new ("sink", GST_PAD_SINK);
317 fail_if (sink == NULL);
318 gst_pad_set_chain_function (sink, gst_check_chain_func);
320 src = gst_pad_new ("src", GST_PAD_SRC);
321 fail_if (src == NULL);
323 caps = gst_caps_from_string ("foo/bar");
325 ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
327 gst_pad_set_caps (src, caps);
328 gst_pad_set_caps (sink, caps);
329 /* one for me and one for each set_caps */
330 ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
332 plr = gst_pad_link (src, sink);
333 fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
334 ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
336 buffer = gst_buffer_new ();
338 /* FIXME, new pad should be flushing */
339 gst_buffer_ref (buffer);
340 fail_unless (gst_pad_push (src, buffer) == GST_FLOW_WRONG_STATE);
341 gst_buffer_ref (buffer);
342 fail_unless (gst_pad_chain (sink, buffer) == GST_FLOW_WRONG_STATE);
346 gst_pad_set_active (src, TRUE);
347 gst_pad_set_active (sink, TRUE);
350 /* pushing on a linked pad will drop the ref to the buffer */
351 gst_buffer_ref (buffer);
352 fail_unless (gst_pad_push (src, buffer) == GST_FLOW_OK);
353 ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 2);
354 gst_buffer_unref (buffer);
355 fail_unless_equals_int (g_list_length (buffers), 1);
356 buffer = GST_BUFFER (buffers->data);
357 ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
358 gst_buffer_unref (buffer);
359 g_list_free (buffers);
362 /* adding a probe that returns FALSE will drop the buffer without trying
364 id = gst_pad_add_buffer_probe (src, (GCallback) _probe_handler,
365 GINT_TO_POINTER (0));
366 buffer = gst_buffer_new ();
367 gst_buffer_ref (buffer);
368 fail_unless (gst_pad_push (src, buffer) == GST_FLOW_OK);
369 ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
370 gst_buffer_unref (buffer);
371 gst_pad_remove_buffer_probe (src, id);
372 fail_unless_equals_int (g_list_length (buffers), 0);
374 /* adding a probe that returns TRUE will still chain the buffer */
375 id = gst_pad_add_buffer_probe (src, (GCallback) _probe_handler,
376 GINT_TO_POINTER (1));
377 buffer = gst_buffer_new ();
378 gst_buffer_ref (buffer);
379 fail_unless (gst_pad_push (src, buffer) == GST_FLOW_OK);
380 gst_pad_remove_buffer_probe (src, id);
382 ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 2);
383 gst_buffer_unref (buffer);
384 fail_unless_equals_int (g_list_length (buffers), 1);
385 buffer = GST_BUFFER (buffers->data);
386 ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
387 gst_buffer_unref (buffer);
388 g_list_free (buffers);
392 gst_pad_unlink (src, sink);
393 ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
394 gst_object_unref (src);
395 gst_object_unref (sink);
396 ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
398 gst_caps_unref (caps);
403 GST_START_TEST (test_flowreturn)
408 /* test some of the macros */
409 ret = GST_FLOW_UNEXPECTED;
410 fail_unless (GST_FLOW_IS_FATAL (ret));
411 fail_if (GST_FLOW_IS_SUCCESS (ret));
412 fail_if (strcmp (gst_flow_get_name (ret), "unexpected"));
413 quark = gst_flow_to_quark (ret);
414 fail_if (strcmp (g_quark_to_string (quark), "unexpected"));
416 ret = GST_FLOW_RESEND;
417 fail_if (GST_FLOW_IS_FATAL (ret));
418 fail_unless (GST_FLOW_IS_SUCCESS (ret));
419 fail_if (strcmp (gst_flow_get_name (ret), "resend"));
420 quark = gst_flow_to_quark (ret);
421 fail_if (strcmp (g_quark_to_string (quark), "resend"));
424 ret = GST_FLOW_CUSTOM_SUCCESS;
425 fail_if (GST_FLOW_IS_FATAL (ret));
426 fail_unless (GST_FLOW_IS_SUCCESS (ret));
427 fail_if (strcmp (gst_flow_get_name (ret), "custom-success"));
428 quark = gst_flow_to_quark (ret);
429 fail_if (strcmp (g_quark_to_string (quark), "custom-success"));
431 ret = GST_FLOW_CUSTOM_ERROR;
432 fail_unless (GST_FLOW_IS_FATAL (ret));
433 fail_if (GST_FLOW_IS_SUCCESS (ret));
434 fail_if (strcmp (gst_flow_get_name (ret), "custom-error"));
435 quark = gst_flow_to_quark (ret);
436 fail_if (strcmp (g_quark_to_string (quark), "custom-error"));
438 /* custom returns clamping */
439 ret = GST_FLOW_CUSTOM_SUCCESS + 2;
440 fail_if (GST_FLOW_IS_FATAL (ret));
441 fail_unless (GST_FLOW_IS_SUCCESS (ret));
442 fail_if (strcmp (gst_flow_get_name (ret), "custom-success"));
443 quark = gst_flow_to_quark (ret);
444 fail_if (strcmp (g_quark_to_string (quark), "custom-success"));
446 ret = GST_FLOW_CUSTOM_ERROR - 2;
447 fail_unless (GST_FLOW_IS_FATAL (ret));
448 fail_if (GST_FLOW_IS_SUCCESS (ret));
449 fail_if (strcmp (gst_flow_get_name (ret), "custom-error"));
450 quark = gst_flow_to_quark (ret);
451 fail_if (strcmp (g_quark_to_string (quark), "custom-error"));
454 ret = GST_FLOW_CUSTOM_ERROR + 2;
455 fail_unless (GST_FLOW_IS_FATAL (ret));
456 fail_if (GST_FLOW_IS_SUCCESS (ret));
457 fail_if (strcmp (gst_flow_get_name (ret), "unknown"));
458 quark = gst_flow_to_quark (ret);
459 fail_unless (quark == 0);
467 Suite *s = suite_create ("GstPad");
468 TCase *tc_chain = tcase_create ("general");
470 /* turn off timeout */
471 tcase_set_timeout (tc_chain, 60);
473 suite_add_tcase (s, tc_chain);
474 tcase_add_test (tc_chain, test_link);
475 tcase_add_test (tc_chain, test_refcount);
476 tcase_add_test (tc_chain, test_get_allowed_caps);
477 tcase_add_test (tc_chain, test_link_unlink_threaded);
478 tcase_add_test (tc_chain, test_name_is_valid);
479 tcase_add_test (tc_chain, test_push_unlinked);
480 tcase_add_test (tc_chain, test_push_linked);
481 tcase_add_test (tc_chain, test_flowreturn);
486 GST_CHECK_MAIN (gst_pad);