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