Merge branch 'master' into 0.11
[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 static GstPad *src, *sink;
67
68 static 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_active (sink, TRUE);
93   gst_pad_set_caps (sink, caps);
94   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
95
96   MAIN_START_THREADS (5, thread_link_unlink, NULL);
97   for (i = 0; i < 1000; ++i) {
98     gst_pad_is_linked (src);
99     gst_pad_is_linked (sink);
100     THREAD_SWITCH ();
101   }
102   MAIN_STOP_THREADS ();
103
104   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
105   gst_caps_unref (caps);
106
107   ASSERT_CAPS_REFCOUNT (caps, "caps", 2);
108   gst_object_unref (src);
109   gst_object_unref (sink);
110 }
111
112 GST_END_TEST;
113
114 GST_START_TEST (test_refcount)
115 {
116   GstPad *src, *sink;
117   GstCaps *caps;
118   GstPadLinkReturn plr;
119
120   sink = gst_pad_new ("sink", GST_PAD_SINK);
121   fail_if (sink == NULL);
122
123   src = gst_pad_new ("src", GST_PAD_SRC);
124   fail_if (src == NULL);
125
126   caps = gst_caps_from_string ("foo/bar");
127   /* one for me */
128   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
129
130   fail_unless (gst_pad_set_caps (src, caps) == TRUE);
131   /* can't set caps on flushing sinkpad */
132   fail_if (gst_pad_set_caps (sink, caps) == TRUE);
133   /* one for me and one for each set_caps */
134   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
135
136   gst_pad_set_active (sink, TRUE);
137   fail_unless (gst_pad_set_caps (sink, caps) == TRUE);
138   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
139
140   plr = gst_pad_link (src, sink);
141   fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
142   /* src caps added to pending caps on sink */
143   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
144
145   gst_pad_unlink (src, sink);
146   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
147
148   /* cleanup */
149   gst_object_unref (src);
150   gst_object_unref (sink);
151   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
152
153   gst_caps_unref (caps);
154 }
155
156 GST_END_TEST;
157
158 GST_START_TEST (test_get_allowed_caps)
159 {
160   GstPad *src, *sink;
161   GstCaps *caps, *gotcaps;
162   GstBuffer *buffer;
163   GstPadLinkReturn plr;
164
165   ASSERT_CRITICAL (gst_pad_get_allowed_caps (NULL));
166
167   buffer = gst_buffer_new ();
168   ASSERT_CRITICAL (gst_pad_get_allowed_caps ((GstPad *) buffer));
169   gst_buffer_unref (buffer);
170
171   src = gst_pad_new ("src", GST_PAD_SRC);
172   fail_if (src == NULL);
173   caps = gst_pad_get_allowed_caps (src);
174   fail_unless (caps == NULL);
175
176   caps = gst_caps_from_string ("foo/bar");
177
178   sink = gst_pad_new ("sink", GST_PAD_SINK);
179   fail_unless (gst_pad_set_caps (src, caps) == TRUE);
180   fail_if (gst_pad_set_caps (sink, caps) == TRUE);
181   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
182
183   gst_pad_set_active (sink, TRUE);
184   fail_unless (gst_pad_set_caps (sink, caps) == TRUE);
185   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
186
187   plr = gst_pad_link (src, sink);
188   fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
189
190   gotcaps = gst_pad_get_allowed_caps (src);
191   fail_if (gotcaps == NULL);
192 #if 0
193   /* FIXME, does not work, caps events are different so the sinkpad loses caps
194    * when linking */
195   fail_unless (gst_caps_is_equal (gotcaps, caps));
196 #endif
197
198   ASSERT_CAPS_REFCOUNT (gotcaps, "gotcaps", 1);
199   gst_caps_unref (gotcaps);
200
201   gst_pad_unlink (src, sink);
202
203   /* cleanup */
204   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
205   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
206   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
207
208   gst_object_unref (src);
209   gst_object_unref (sink);
210
211   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
212   gst_caps_unref (caps);
213 }
214
215 GST_END_TEST;
216
217 static gboolean
218 name_is_valid (const gchar * name, GstPadPresence presence)
219 {
220   GstPadTemplate *new;
221   GstCaps *any = gst_caps_new_any ();
222
223   new = gst_pad_template_new (name, GST_PAD_SRC, presence, any);
224   gst_caps_unref (any);
225   if (new) {
226     gst_object_unref (GST_OBJECT (new));
227     return TRUE;
228   }
229   return FALSE;
230 }
231
232 GST_START_TEST (test_name_is_valid)
233 {
234   gboolean result = FALSE;
235
236   fail_unless (name_is_valid ("src", GST_PAD_ALWAYS));
237   ASSERT_WARNING (name_is_valid ("src%", GST_PAD_ALWAYS));
238   ASSERT_WARNING (result = name_is_valid ("src%d", GST_PAD_ALWAYS));
239   fail_if (result);
240
241   fail_unless (name_is_valid ("src", GST_PAD_REQUEST));
242   ASSERT_WARNING (name_is_valid ("src%s%s", GST_PAD_REQUEST));
243   ASSERT_WARNING (name_is_valid ("src%c", GST_PAD_REQUEST));
244   ASSERT_WARNING (name_is_valid ("src%", GST_PAD_REQUEST));
245   ASSERT_WARNING (name_is_valid ("src%dsrc", GST_PAD_REQUEST));
246
247   fail_unless (name_is_valid ("src", GST_PAD_SOMETIMES));
248   fail_unless (name_is_valid ("src%c", GST_PAD_SOMETIMES));
249 }
250
251 GST_END_TEST;
252
253 static GstProbeReturn
254 _probe_handler (GstPad * pad, GstProbeType type, GstBuffer * buffer,
255     gpointer userdata)
256 {
257   gint ret = GPOINTER_TO_INT (userdata);
258
259   if (ret == 1)
260     return GST_PROBE_OK;
261
262   return GST_PROBE_DROP;
263 }
264
265 GST_START_TEST (test_push_unlinked)
266 {
267   GstPad *src;
268   GstCaps *caps;
269   GstBuffer *buffer;
270   gulong id;
271
272   src = gst_pad_new ("src", GST_PAD_SRC);
273   fail_if (src == NULL);
274   caps = gst_pad_get_allowed_caps (src);
275   fail_unless (caps == NULL);
276
277   caps = gst_caps_from_string ("foo/bar");
278
279   gst_pad_set_caps (src, caps);
280   ASSERT_CAPS_REFCOUNT (caps, "caps", 2);
281
282   /* pushing on an inactive pad will return wrong state */
283   buffer = gst_buffer_new ();
284   gst_buffer_ref (buffer);
285   fail_unless (gst_pad_push (src, buffer) == GST_FLOW_WRONG_STATE);
286   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
287   gst_buffer_unref (buffer);
288
289   gst_pad_set_active (src, TRUE);
290
291   /* pushing on an unlinked pad will drop the buffer */
292   buffer = gst_buffer_new ();
293   gst_buffer_ref (buffer);
294   fail_unless (gst_pad_push (src, buffer) == GST_FLOW_NOT_LINKED);
295   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
296   gst_buffer_unref (buffer);
297
298   /* adding a probe that returns FALSE will drop the buffer without trying
299    * to chain */
300   id = gst_pad_add_probe (src, GST_PROBE_TYPE_BUFFER,
301       (GstPadProbeCallback) _probe_handler, GINT_TO_POINTER (0), NULL);
302   buffer = gst_buffer_new ();
303   gst_buffer_ref (buffer);
304   fail_unless (gst_pad_push (src, buffer) == GST_FLOW_OK);
305   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
306   gst_buffer_unref (buffer);
307   gst_pad_remove_probe (src, id);
308
309   /* adding a probe that returns TRUE will still chain the buffer,
310    * and hence drop because pad is unlinked */
311   id = gst_pad_add_probe (src, GST_PROBE_TYPE_BUFFER,
312       (GstPadProbeCallback) _probe_handler, GINT_TO_POINTER (1), NULL);
313   buffer = gst_buffer_new ();
314   gst_buffer_ref (buffer);
315   fail_unless (gst_pad_push (src, buffer) == GST_FLOW_NOT_LINKED);
316   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
317   gst_buffer_unref (buffer);
318   gst_pad_remove_probe (src, id);
319
320
321   /* cleanup */
322   ASSERT_CAPS_REFCOUNT (caps, "caps", 2);
323   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
324
325   gst_object_unref (src);
326
327   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
328   gst_caps_unref (caps);
329 }
330
331 GST_END_TEST;
332
333 GST_START_TEST (test_push_linked)
334 {
335   GstPad *src, *sink;
336   GstPadLinkReturn plr;
337   GstCaps *caps;
338   GstBuffer *buffer;
339   gulong id;
340
341   /* setup */
342   sink = gst_pad_new ("sink", GST_PAD_SINK);
343   fail_if (sink == NULL);
344   gst_pad_set_chain_function (sink, gst_check_chain_func);
345
346   src = gst_pad_new ("src", GST_PAD_SRC);
347   fail_if (src == NULL);
348
349   caps = gst_caps_from_string ("foo/bar");
350   /* one for me */
351   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
352
353   gst_pad_set_caps (src, caps);
354   gst_pad_set_active (sink, TRUE);
355   gst_pad_set_caps (sink, caps);
356   /* one for me and one for each set_caps */
357   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
358
359   plr = gst_pad_link (src, sink);
360   fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
361   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
362
363   buffer = gst_buffer_new ();
364 #if 0
365   /* FIXME, new pad should be flushing */
366   gst_buffer_ref (buffer);
367   fail_unless (gst_pad_push (src, buffer) == GST_FLOW_WRONG_STATE);
368   gst_buffer_ref (buffer);
369   fail_unless (gst_pad_chain (sink, buffer) == GST_FLOW_WRONG_STATE);
370 #endif
371
372   /* activate pads */
373   gst_pad_set_active (src, TRUE);
374   gst_pad_set_active (sink, TRUE);
375
376   /* test */
377   /* pushing on a linked pad will drop the ref to the buffer */
378   gst_buffer_ref (buffer);
379   fail_unless (gst_pad_push (src, buffer) == GST_FLOW_OK);
380   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 2);
381   gst_buffer_unref (buffer);
382   fail_unless_equals_int (g_list_length (buffers), 1);
383   buffer = GST_BUFFER (buffers->data);
384   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
385   gst_buffer_unref (buffer);
386   g_list_free (buffers);
387   buffers = NULL;
388
389   /* adding a probe that returns FALSE will drop the buffer without trying
390    * to chain */
391   id = gst_pad_add_probe (src, GST_PROBE_TYPE_BUFFER,
392       (GstPadProbeCallback) _probe_handler, GINT_TO_POINTER (0), NULL);
393   buffer = gst_buffer_new ();
394   gst_buffer_ref (buffer);
395   fail_unless (gst_pad_push (src, buffer) == GST_FLOW_OK);
396   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
397   gst_buffer_unref (buffer);
398   gst_pad_remove_probe (src, id);
399   fail_unless_equals_int (g_list_length (buffers), 0);
400
401   /* adding a probe that returns TRUE will still chain the buffer */
402   id = gst_pad_add_probe (src, GST_PROBE_TYPE_BUFFER,
403       (GstPadProbeCallback) _probe_handler, GINT_TO_POINTER (1), NULL);
404   buffer = gst_buffer_new ();
405   gst_buffer_ref (buffer);
406   fail_unless (gst_pad_push (src, buffer) == GST_FLOW_OK);
407   gst_pad_remove_probe (src, id);
408
409   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 2);
410   gst_buffer_unref (buffer);
411   fail_unless_equals_int (g_list_length (buffers), 1);
412   buffer = GST_BUFFER (buffers->data);
413   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
414   gst_buffer_unref (buffer);
415   g_list_free (buffers);
416   buffers = NULL;
417
418   /* teardown */
419   gst_pad_unlink (src, sink);
420   ASSERT_CAPS_REFCOUNT (caps, "caps", 2);
421   gst_object_unref (src);
422   gst_object_unref (sink);
423   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
424
425   gst_caps_unref (caps);
426 }
427
428 GST_END_TEST;
429
430 static GstBuffer *
431 buffer_from_string (const gchar * str)
432 {
433   guint size;
434   GstBuffer *buf;
435   gpointer data;
436
437   size = strlen (str);
438   buf = gst_buffer_new_and_alloc (size);
439
440   data = gst_buffer_map (buf, NULL, NULL, GST_MAP_WRITE);
441   memcpy (data, str, size);
442   gst_buffer_unmap (buf, data, size);
443
444   return buf;
445 }
446
447 static gboolean
448 buffer_compare (GstBuffer * buf, const gchar * str, gsize size)
449 {
450   gboolean res;
451   gpointer data;
452
453   data = gst_buffer_map (buf, NULL, NULL, GST_MAP_READ);
454   res = memcmp (data, str, size) == 0;
455   GST_DEBUG ("%s <-> %s: %d", (gchar *) data, str, res);
456   gst_buffer_unmap (buf, data, size);
457
458   return res;
459 }
460
461 GST_START_TEST (test_push_buffer_list_compat)
462 {
463   GstPad *src, *sink;
464   GstPadLinkReturn plr;
465   GstCaps *caps;
466   GstBufferList *list;
467   GstBuffer *buffer;
468
469   /* setup */
470   sink = gst_pad_new ("sink", GST_PAD_SINK);
471   fail_if (sink == NULL);
472   gst_pad_set_chain_function (sink, gst_check_chain_func);
473   /* leave chainlistfunc unset */
474
475   src = gst_pad_new ("src", GST_PAD_SRC);
476   fail_if (src == NULL);
477
478   caps = gst_caps_from_string ("foo/bar");
479
480   gst_pad_set_caps (src, caps);
481   gst_pad_set_active (sink, TRUE);
482   gst_pad_set_caps (sink, caps);
483
484   plr = gst_pad_link (src, sink);
485   fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
486
487   list = gst_buffer_list_new ();
488
489   /* activate pads */
490   gst_pad_set_active (src, TRUE);
491   gst_pad_set_active (sink, TRUE);
492
493   /* test */
494   /* adding to a buffer list will drop the ref to the buffer */
495   gst_buffer_list_add (list, buffer_from_string ("ListGroup"));
496   gst_buffer_list_add (list, buffer_from_string ("AnotherListGroup"));
497
498   fail_unless (gst_pad_push_list (src, list) == GST_FLOW_OK);
499   fail_unless_equals_int (g_list_length (buffers), 2);
500   buffer = GST_BUFFER (buffers->data);
501   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
502   fail_unless (buffer_compare (buffer, "ListGroup", 9));
503   gst_buffer_unref (buffer);
504   buffers = g_list_delete_link (buffers, buffers);
505   buffer = GST_BUFFER (buffers->data);
506   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
507   fail_unless (buffer_compare (buffer, "AnotherListGroup", 16));
508   gst_buffer_unref (buffer);
509   buffers = g_list_delete_link (buffers, buffers);
510   fail_unless (buffers == NULL);
511
512   /* teardown */
513   gst_pad_unlink (src, sink);
514   gst_object_unref (src);
515   gst_object_unref (sink);
516   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
517   gst_caps_unref (caps);
518 }
519
520 GST_END_TEST;
521
522 GST_START_TEST (test_flowreturn)
523 {
524   GstFlowReturn ret;
525   GQuark quark;
526
527   /* test some of the macros */
528   ret = GST_FLOW_EOS;
529   fail_if (strcmp (gst_flow_get_name (ret), "eos"));
530   quark = gst_flow_to_quark (ret);
531   fail_if (strcmp (g_quark_to_string (quark), "eos"));
532
533   ret = GST_FLOW_RESEND;
534   fail_if (strcmp (gst_flow_get_name (ret), "resend"));
535   quark = gst_flow_to_quark (ret);
536   fail_if (strcmp (g_quark_to_string (quark), "resend"));
537
538   /* custom returns */
539   ret = GST_FLOW_CUSTOM_SUCCESS;
540   fail_if (strcmp (gst_flow_get_name (ret), "custom-success"));
541   quark = gst_flow_to_quark (ret);
542   fail_if (strcmp (g_quark_to_string (quark), "custom-success"));
543
544   ret = GST_FLOW_CUSTOM_ERROR;
545   fail_if (strcmp (gst_flow_get_name (ret), "custom-error"));
546   quark = gst_flow_to_quark (ret);
547   fail_if (strcmp (g_quark_to_string (quark), "custom-error"));
548
549   /* custom returns clamping */
550   ret = GST_FLOW_CUSTOM_SUCCESS + 2;
551   fail_if (strcmp (gst_flow_get_name (ret), "custom-success"));
552   quark = gst_flow_to_quark (ret);
553   fail_if (strcmp (g_quark_to_string (quark), "custom-success"));
554
555   ret = GST_FLOW_CUSTOM_ERROR - 2;
556   fail_if (strcmp (gst_flow_get_name (ret), "custom-error"));
557   quark = gst_flow_to_quark (ret);
558   fail_if (strcmp (g_quark_to_string (quark), "custom-error"));
559
560   /* unknown values */
561   ret = GST_FLOW_CUSTOM_ERROR + 2;
562   fail_if (strcmp (gst_flow_get_name (ret), "unknown"));
563   quark = gst_flow_to_quark (ret);
564   fail_unless (quark == 0);
565 }
566
567 GST_END_TEST;
568
569 GST_START_TEST (test_push_negotiation)
570 {
571   GstPad *src, *sink;
572   GstPadLinkReturn plr;
573   GstCaps *srccaps =
574       gst_caps_from_string ("audio/x-raw-int,width={16,32},depth={16,32}");
575   GstCaps *sinkcaps =
576       gst_caps_from_string ("audio/x-raw-int,width=32,depth={16,32}");
577   GstPadTemplate *src_template;
578   GstPadTemplate *sink_template;
579   GstCaps *caps;
580
581   /* setup */
582   src_template = gst_pad_template_new ("src", GST_PAD_SRC,
583       GST_PAD_ALWAYS, srccaps);
584   sink_template = gst_pad_template_new ("sink", GST_PAD_SINK,
585       GST_PAD_ALWAYS, sinkcaps);
586   gst_caps_unref (srccaps);
587   gst_caps_unref (sinkcaps);
588
589   sink = gst_pad_new_from_template (sink_template, "sink");
590   fail_if (sink == NULL);
591   gst_pad_set_chain_function (sink, gst_check_chain_func);
592
593   src = gst_pad_new_from_template (src_template, "src");
594   fail_if (src == NULL);
595
596   plr = gst_pad_link (src, sink);
597   fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
598
599   /* activate pads */
600   gst_pad_set_active (src, TRUE);
601   gst_pad_set_active (sink, TRUE);
602
603   caps = gst_caps_from_string ("audio/x-raw-int,width=16,depth=16");
604
605   /* Should fail if src pad caps are incompatible with sink pad caps */
606   gst_pad_set_caps (src, caps);
607   fail_unless (gst_pad_set_caps (sink, caps) == FALSE);
608
609   /* teardown */
610   gst_pad_unlink (src, sink);
611   gst_object_unref (src);
612   gst_object_unref (sink);
613   gst_caps_unref (caps);
614   gst_object_unref (sink_template);
615   gst_object_unref (src_template);
616 }
617
618 GST_END_TEST;
619
620 /* see that an unref also unlinks the pads */
621 GST_START_TEST (test_src_unref_unlink)
622 {
623   GstPad *src, *sink;
624   GstCaps *caps;
625   GstPadLinkReturn plr;
626
627   sink = gst_pad_new ("sink", GST_PAD_SINK);
628   fail_if (sink == NULL);
629
630   src = gst_pad_new ("src", GST_PAD_SRC);
631   fail_if (src == NULL);
632
633   caps = gst_caps_from_string ("foo/bar");
634
635   gst_pad_set_caps (src, caps);
636   gst_pad_set_active (sink, TRUE);
637   gst_pad_set_caps (sink, caps);
638
639   plr = gst_pad_link (src, sink);
640   fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
641
642   /* unref the srcpad */
643   gst_object_unref (src);
644
645   /* sink should be unlinked now */
646   fail_if (gst_pad_is_linked (sink));
647
648   /* cleanup */
649   gst_object_unref (sink);
650   gst_caps_unref (caps);
651 }
652
653 GST_END_TEST;
654
655 /* see that an unref also unlinks the pads */
656 GST_START_TEST (test_sink_unref_unlink)
657 {
658   GstPad *src, *sink;
659   GstCaps *caps;
660   GstPadLinkReturn plr;
661
662   sink = gst_pad_new ("sink", GST_PAD_SINK);
663   fail_if (sink == NULL);
664
665   src = gst_pad_new ("src", GST_PAD_SRC);
666   fail_if (src == NULL);
667
668   caps = gst_caps_from_string ("foo/bar");
669
670   gst_pad_set_caps (src, caps);
671   gst_pad_set_active (sink, TRUE);
672   gst_pad_set_caps (sink, caps);
673
674   plr = gst_pad_link (src, sink);
675   fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
676
677   /* unref the sinkpad */
678   gst_object_unref (sink);
679
680   /* src should be unlinked now */
681   fail_if (gst_pad_is_linked (src));
682
683   /* cleanup */
684   gst_object_unref (src);
685   gst_caps_unref (caps);
686 }
687
688 GST_END_TEST;
689
690 static gulong id;
691
692 static GstProbeReturn
693 block_async_cb (GstPad * pad, GstProbeType type, gpointer type_data,
694     gpointer user_data)
695 {
696   gboolean *bool_user_data = (gboolean *) user_data;
697
698   fail_unless ((type & GST_PROBE_TYPE_BLOCK) != 0);
699
700   /* here we should have blocked == 0 unblocked == 0 */
701   fail_unless (bool_user_data[0] == FALSE);
702   fail_unless (bool_user_data[1] == FALSE);
703
704   bool_user_data[0] = TRUE;
705
706   gst_pad_remove_probe (pad, id);
707   bool_user_data[1] = TRUE;
708
709   return GST_PROBE_OK;
710 }
711
712 GST_START_TEST (test_block_async)
713 {
714   GstPad *pad;
715   /* we set data[0] = TRUE when the pad is blocked, data[1] = TRUE when it's
716    * unblocked */
717   gboolean data[2] = { FALSE, FALSE };
718
719   pad = gst_pad_new ("src", GST_PAD_SRC);
720   fail_unless (pad != NULL);
721
722   gst_pad_set_active (pad, TRUE);
723   id = gst_pad_add_probe (pad, GST_PROBE_TYPE_BLOCK, block_async_cb, &data,
724       NULL);
725
726   fail_unless (data[0] == FALSE);
727   fail_unless (data[1] == FALSE);
728   gst_pad_push (pad, gst_buffer_new ());
729
730   gst_object_unref (pad);
731 }
732
733 GST_END_TEST;
734
735 #if 0
736 static void
737 block_async_second (GstPad * pad, gboolean blocked, gpointer user_data)
738 {
739   gst_pad_set_blocked (pad, FALSE, unblock_async_cb, NULL, NULL);
740 }
741
742 static void
743 block_async_first (GstPad * pad, gboolean blocked, gpointer user_data)
744 {
745   static int n_calls = 0;
746   gboolean *bool_user_data = (gboolean *) user_data;
747
748   if (++n_calls > 1)
749     /* we expect this callback to be called only once */
750     g_warn_if_reached ();
751
752   *bool_user_data = blocked;
753
754   /* replace block_async_first with block_async_second so next time the pad is
755    * blocked the latter should be called */
756   gst_pad_set_blocked (pad, TRUE, block_async_second, NULL, NULL);
757
758   /* unblock temporarily, in the next push block_async_second should be called
759    */
760   gst_pad_push_event (pad, gst_event_new_flush_start ());
761 }
762
763 GST_START_TEST (test_block_async_replace_callback)
764 {
765   GstPad *pad;
766   gboolean blocked;
767
768   pad = gst_pad_new ("src", GST_PAD_SRC);
769   fail_unless (pad != NULL);
770   gst_pad_set_active (pad, TRUE);
771
772   gst_pad_set_blocked (pad, TRUE, block_async_first, &blocked, NULL);
773   blocked = FALSE;
774
775   gst_pad_push (pad, gst_buffer_new ());
776   fail_unless (blocked == TRUE);
777   /* block_async_first flushes to unblock */
778   gst_pad_push_event (pad, gst_event_new_flush_stop ());
779
780   /* push again, this time block_async_second should be called */
781   gst_pad_push (pad, gst_buffer_new ());
782   fail_unless (blocked == TRUE);
783
784   gst_object_unref (pad);
785 }
786
787 GST_END_TEST;
788 #endif
789
790 static void
791 block_async_full_destroy (gpointer user_data)
792 {
793   gint *state = (gint *) user_data;
794
795   fail_unless (*state < 2);
796
797   GST_DEBUG ("setting state to 2");
798   *state = 2;
799 }
800
801 static GstProbeReturn
802 block_async_full_cb (GstPad * pad, GstProbeType type, gpointer type_data,
803     gpointer user_data)
804 {
805   *(gint *) user_data = (gint) TRUE;
806
807   gst_pad_push_event (pad, gst_event_new_flush_start ());
808   GST_DEBUG ("setting state to 1");
809
810   return GST_PROBE_OK;
811 }
812
813 GST_START_TEST (test_block_async_full_destroy)
814 {
815   GstPad *pad;
816   /* 0 = unblocked, 1 = blocked, 2 = destroyed */
817   gint state = 0;
818   gulong id;
819
820   pad = gst_pad_new ("src", GST_PAD_SRC);
821   fail_unless (pad != NULL);
822   gst_pad_set_active (pad, TRUE);
823
824   id = gst_pad_add_probe (pad, GST_PROBE_TYPE_BLOCK, block_async_full_cb,
825       &state, block_async_full_destroy);
826   fail_unless (state == 0);
827
828   gst_pad_push (pad, gst_buffer_new ());
829   /* block_async_full_cb sets state to 1 and then flushes to unblock temporarily
830    */
831   fail_unless (state == 1);
832   gst_pad_push_event (pad, gst_event_new_flush_stop (TRUE));
833
834   /* unblock callback is called */
835   gst_pad_remove_probe (pad, id);
836   fail_unless (state == 2);
837
838   gst_object_unref (pad);
839 }
840
841 GST_END_TEST;
842
843 GST_START_TEST (test_block_async_full_destroy_dispose)
844 {
845   GstPad *pad;
846   /* 0 = unblocked, 1 = blocked, 2 = destroyed */
847   gint state = 0;
848
849   pad = gst_pad_new ("src", GST_PAD_SRC);
850   fail_unless (pad != NULL);
851   gst_pad_set_active (pad, TRUE);
852
853   (void) gst_pad_add_probe (pad, GST_PROBE_TYPE_BLOCK, block_async_full_cb,
854       &state, block_async_full_destroy);
855
856   gst_pad_push (pad, gst_buffer_new ());
857   /* block_async_full_cb sets state to 1 and then flushes to unblock temporarily
858    */
859   fail_unless_equals_int (state, 1);
860   gst_pad_push_event (pad, gst_event_new_flush_stop (TRUE));
861
862   /* gst_BLOCK calls the destroy_notify function if necessary */
863   gst_object_unref (pad);
864
865   fail_unless_equals_int (state, 2);
866 }
867
868 GST_END_TEST;
869
870
871 #if 0
872 static void
873 unblock_async_no_flush_cb (GstPad * pad, gboolean blocked, gpointer user_data)
874 {
875   gboolean *bool_user_data = (gboolean *) user_data;
876
877   /* here we should have blocked == 1 unblocked == 0 */
878
879   fail_unless (blocked == FALSE);
880
881   fail_unless (bool_user_data[0] == TRUE);
882   fail_unless (bool_user_data[1] == TRUE);
883   fail_unless (bool_user_data[2] == FALSE);
884
885   bool_user_data[2] = TRUE;
886 }
887 #endif
888
889
890 #if 0
891 static void
892 unblock_async_not_called (GstPad * pad, gboolean blocked, gpointer user_data)
893 {
894   g_warn_if_reached ();
895 }
896 #endif
897
898 static GstProbeReturn
899 block_async_second_no_flush (GstPad * pad, GstProbeType type,
900     gpointer type_data, gpointer user_data)
901 {
902   gboolean *bool_user_data = (gboolean *) user_data;
903
904   GST_DEBUG ("second probe called");
905
906   fail_unless (type & GST_PROBE_TYPE_BLOCK);
907
908   fail_unless (bool_user_data[0] == TRUE);
909   fail_unless (bool_user_data[1] == FALSE);
910   fail_unless (bool_user_data[2] == FALSE);
911
912   bool_user_data[1] = TRUE;
913
914   GST_DEBUG ("removing second probe with id %lu", id);
915   gst_pad_remove_probe (pad, id);
916
917   return GST_PROBE_OK;
918 }
919
920 static GstProbeReturn
921 block_async_first_no_flush (GstPad * pad, GstProbeType type, gpointer type_data,
922     gpointer user_data)
923 {
924   static int n_calls = 0;
925   gboolean *bool_user_data = (gboolean *) user_data;
926
927   fail_unless (type & GST_PROBE_TYPE_BLOCK);
928
929   GST_DEBUG ("first probe called");
930
931   if (++n_calls > 1)
932     /* we expect this callback to be called only once */
933     g_warn_if_reached ();
934
935   *bool_user_data = TRUE;
936
937   fail_unless (bool_user_data[0] == TRUE);
938   fail_unless (bool_user_data[1] == FALSE);
939   fail_unless (bool_user_data[2] == FALSE);
940
941   GST_DEBUG ("removing first probe with id %lu", id);
942   gst_pad_remove_probe (pad, id);
943
944   GST_DEBUG ("adding second probe");
945   /* replace block_async_first with block_async_second so next time the pad is
946    * blocked the latter should be called */
947   id = gst_pad_add_probe (pad, GST_PROBE_TYPE_BLOCK,
948       block_async_second_no_flush, user_data, NULL);
949   GST_DEBUG ("added probe with id %lu", id);
950
951   return GST_PROBE_OK;
952 }
953
954 GST_START_TEST (test_block_async_replace_callback_no_flush)
955 {
956   GstPad *pad;
957   gboolean bool_user_data[3] = { FALSE, FALSE, FALSE };
958
959   pad = gst_pad_new ("src", GST_PAD_SRC);
960   fail_unless (pad != NULL);
961   gst_pad_set_active (pad, TRUE);
962
963   GST_DEBUG ("adding probe");
964   id = gst_pad_add_probe (pad, GST_PROBE_TYPE_BLOCK,
965       block_async_first_no_flush, bool_user_data, NULL);
966   GST_DEBUG ("added probe with id %lu", id);
967   fail_if (id == 0);
968
969   GST_DEBUG ("pushing buffer");
970   gst_pad_push (pad, gst_buffer_new ());
971   fail_unless (bool_user_data[0] == TRUE);
972   fail_unless (bool_user_data[1] == TRUE);
973   fail_unless (bool_user_data[2] == FALSE);
974
975   gst_object_unref (pad);
976 }
977
978 GST_END_TEST;
979
980
981 static Suite *
982 gst_pad_suite (void)
983 {
984   Suite *s = suite_create ("GstPad");
985   TCase *tc_chain = tcase_create ("general");
986
987   /* turn off timeout */
988   tcase_set_timeout (tc_chain, 60);
989
990   suite_add_tcase (s, tc_chain);
991   tcase_add_test (tc_chain, test_link);
992   tcase_add_test (tc_chain, test_refcount);
993   tcase_add_test (tc_chain, test_get_allowed_caps);
994   tcase_add_test (tc_chain, test_link_unlink_threaded);
995   tcase_add_test (tc_chain, test_name_is_valid);
996   tcase_add_test (tc_chain, test_push_unlinked);
997   tcase_add_test (tc_chain, test_push_linked);
998   tcase_add_test (tc_chain, test_push_buffer_list_compat);
999   tcase_add_test (tc_chain, test_flowreturn);
1000   tcase_add_test (tc_chain, test_push_negotiation);
1001   tcase_add_test (tc_chain, test_src_unref_unlink);
1002   tcase_add_test (tc_chain, test_sink_unref_unlink);
1003   tcase_add_test (tc_chain, test_block_async);
1004 #if 0
1005   tcase_add_test (tc_chain, test_block_async_replace_callback);
1006 #endif
1007   tcase_add_test (tc_chain, test_block_async_full_destroy);
1008   tcase_add_test (tc_chain, test_block_async_full_destroy_dispose);
1009   tcase_add_test (tc_chain, test_block_async_replace_callback_no_flush);
1010
1011   return s;
1012 }
1013
1014 GST_CHECK_MAIN (gst_pad);