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