pad: fix blocking probe emission
[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 #include <glib/gthread.h>
24
25 GST_START_TEST (test_link)
26 {
27   GstPad *src, *sink;
28   GstPadTemplate *srct;
29
30   GstPadLinkReturn ret;
31   gchar *name;
32
33   src = gst_pad_new ("source", GST_PAD_SRC);
34   fail_if (src == NULL);
35   ASSERT_OBJECT_REFCOUNT (src, "source pad", 1);
36
37   name = gst_pad_get_name (src);
38   fail_unless (strcmp (name, "source") == 0);
39   ASSERT_OBJECT_REFCOUNT (src, "source pad", 1);
40   g_free (name);
41
42   sink = gst_pad_new ("sink", GST_PAD_SINK);
43   fail_if (sink == NULL);
44
45   /* linking without templates or caps should fail */
46   ret = gst_pad_link (src, sink);
47   ASSERT_OBJECT_REFCOUNT (src, "source pad", 1);
48   ASSERT_OBJECT_REFCOUNT (sink, "sink pad", 1);
49   fail_unless (ret == GST_PAD_LINK_NOFORMAT);
50
51   ASSERT_CRITICAL (gst_pad_get_pad_template (NULL));
52
53   srct = gst_pad_get_pad_template (src);
54   fail_unless (srct == NULL);
55   ASSERT_OBJECT_REFCOUNT (src, "source pad", 1);
56
57   /* clean up */
58   ASSERT_OBJECT_REFCOUNT (src, "source pad", 1);
59   gst_object_unref (src);
60   gst_object_unref (sink);
61 }
62
63 GST_END_TEST;
64
65 /* threaded link/unlink */
66 /* use globals */
67 static GstPad *src, *sink;
68
69 static void
70 thread_link_unlink (gpointer data)
71 {
72   THREAD_START ();
73
74   while (THREAD_TEST_RUNNING ()) {
75     gst_pad_link (src, sink);
76     gst_pad_unlink (src, sink);
77     THREAD_SWITCH ();
78   }
79 }
80
81 GST_START_TEST (test_link_unlink_threaded)
82 {
83   GstCaps *caps;
84   int i;
85
86   src = gst_pad_new ("source", GST_PAD_SRC);
87   fail_if (src == NULL);
88   sink = gst_pad_new ("sink", GST_PAD_SINK);
89   fail_if (sink == NULL);
90
91   caps = gst_caps_from_string ("foo/bar");
92   gst_pad_set_active (src, TRUE);
93   gst_pad_set_caps (src, caps);
94   gst_pad_set_active (sink, TRUE);
95   gst_pad_set_caps (sink, caps);
96   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
97
98   MAIN_START_THREADS (5, thread_link_unlink, NULL);
99   for (i = 0; i < 1000; ++i) {
100     gst_pad_is_linked (src);
101     gst_pad_is_linked (sink);
102     THREAD_SWITCH ();
103   }
104   MAIN_STOP_THREADS ();
105
106   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
107   gst_caps_unref (caps);
108
109   ASSERT_CAPS_REFCOUNT (caps, "caps", 2);
110   gst_object_unref (src);
111   gst_object_unref (sink);
112 }
113
114 GST_END_TEST;
115
116 GST_START_TEST (test_refcount)
117 {
118   GstPad *src, *sink;
119   GstCaps *caps;
120   GstPadLinkReturn plr;
121
122   sink = gst_pad_new ("sink", GST_PAD_SINK);
123   fail_if (sink == NULL);
124
125   src = gst_pad_new ("src", GST_PAD_SRC);
126   fail_if (src == NULL);
127
128   caps = gst_caps_from_string ("foo/bar");
129   /* one for me */
130   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
131
132   /* can't set caps on flushing sinkpad */
133   fail_if (gst_pad_set_caps (src, caps) == TRUE);
134   fail_if (gst_pad_set_caps (sink, caps) == TRUE);
135   /* one for me and one for each set_caps */
136   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
137
138   gst_pad_set_active (src, TRUE);
139   fail_unless (gst_pad_set_caps (src, caps) == TRUE);
140   ASSERT_CAPS_REFCOUNT (caps, "caps", 2);
141
142   gst_pad_set_active (sink, TRUE);
143   fail_unless (gst_pad_set_caps (sink, caps) == TRUE);
144   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
145
146   plr = gst_pad_link (src, sink);
147   fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
148   /* src caps added to pending caps on sink */
149   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
150
151   gst_pad_unlink (src, sink);
152   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
153
154   /* cleanup */
155   gst_object_unref (src);
156   gst_object_unref (sink);
157   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
158
159   gst_caps_unref (caps);
160 }
161
162 GST_END_TEST;
163
164 GST_START_TEST (test_get_allowed_caps)
165 {
166   GstPad *src, *sink;
167   GstCaps *caps, *gotcaps;
168   GstBuffer *buffer;
169   GstPadLinkReturn plr;
170
171   ASSERT_CRITICAL (gst_pad_get_allowed_caps (NULL));
172
173   buffer = gst_buffer_new ();
174   ASSERT_CRITICAL (gst_pad_get_allowed_caps ((GstPad *) buffer));
175   gst_buffer_unref (buffer);
176
177   src = gst_pad_new ("src", GST_PAD_SRC);
178   fail_if (src == NULL);
179   caps = gst_pad_get_allowed_caps (src);
180   fail_unless (caps == NULL);
181
182   caps = gst_caps_from_string ("foo/bar");
183
184   sink = gst_pad_new ("sink", GST_PAD_SINK);
185   gst_pad_set_active (src, TRUE);
186   /* source pad is active and will accept the caps event */
187   fail_unless (gst_pad_set_caps (src, caps) == TRUE);
188   /* sink pad is not active and will refuse the caps event */
189   fail_if (gst_pad_set_caps (sink, caps) == TRUE);
190   ASSERT_CAPS_REFCOUNT (caps, "caps", 2);
191
192   gst_pad_set_active (sink, TRUE);
193   /* sink pad is now active and will accept the caps event */
194   fail_unless (gst_pad_set_caps (sink, caps) == TRUE);
195   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
196
197   plr = gst_pad_link (src, sink);
198   fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
199
200   gotcaps = gst_pad_get_allowed_caps (src);
201   fail_if (gotcaps == NULL);
202   fail_unless (gst_caps_is_equal (gotcaps, caps));
203
204   ASSERT_CAPS_REFCOUNT (gotcaps, "gotcaps", 1);
205   gst_caps_unref (gotcaps);
206
207   gst_pad_unlink (src, sink);
208
209   /* cleanup */
210   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
211   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
212   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
213
214   gst_object_unref (src);
215   gst_object_unref (sink);
216
217   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
218   gst_caps_unref (caps);
219 }
220
221 GST_END_TEST;
222
223 static GstCaps *event_caps = NULL;
224
225 static gboolean
226 sticky_event (GstPad * pad, GstObject * parent, GstEvent * event)
227 {
228   GstCaps *caps;
229
230   fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_CAPS);
231
232   /* Ensure we get here just once: */
233   fail_unless (event_caps == NULL);
234
235   /* The event must arrive before any buffer: */
236   fail_unless_equals_int (g_list_length (buffers), 0);
237
238   gst_event_parse_caps (event, &caps);
239   event_caps = gst_caps_ref (caps);
240
241   gst_event_unref (event);
242
243   return TRUE;
244 }
245
246 /* Tests whether caps get properly forwarded when pads
247    are initially unlinked */
248 GST_START_TEST (test_sticky_caps_unlinked)
249 {
250   GstCaps *caps;
251   GstPadTemplate *src_template, *sink_template;
252   GstPad *src, *sink;
253   GstEvent *event;
254
255   caps = gst_caps_from_string ("foo/bar, dummy=(int){1, 2}");
256   src_template = gst_pad_template_new ("src", GST_PAD_SRC,
257       GST_PAD_ALWAYS, caps);
258   sink_template = gst_pad_template_new ("sink", GST_PAD_SINK,
259       GST_PAD_ALWAYS, caps);
260   gst_caps_unref (caps);
261
262   src = gst_pad_new_from_template (src_template, "src");
263   fail_if (src == NULL);
264   sink = gst_pad_new_from_template (sink_template, "sink");
265   fail_if (sink == NULL);
266   gst_pad_set_event_function (sink, sticky_event);
267   gst_pad_set_chain_function (sink, gst_check_chain_func);
268
269   gst_object_unref (src_template);
270   gst_object_unref (sink_template);
271
272   caps = gst_caps_from_string ("foo/bar, dummy=(int)1");
273   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
274
275   event = gst_event_new_caps (caps);
276   gst_pad_set_active (src, TRUE);
277   fail_unless (gst_pad_push_event (src, event) == TRUE);
278   fail_unless (event_caps == NULL);
279
280   /* Linking and activating will not forward the sticky event yet... */
281   fail_unless (GST_PAD_LINK_SUCCESSFUL (gst_pad_link (src, sink)));
282   gst_pad_set_active (sink, TRUE);
283   fail_unless (event_caps == NULL);
284
285   /* ...but the first buffer will: */
286   fail_unless (gst_pad_push (src, gst_buffer_new ()) == GST_FLOW_OK);
287   fail_unless (event_caps == caps);
288   fail_unless_equals_int (g_list_length (buffers), 1);
289
290   gst_caps_replace (&caps, NULL);
291   gst_caps_replace (&event_caps, NULL);
292
293   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
294   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
295   gst_object_unref (src);
296   gst_object_unref (sink);
297 }
298
299 GST_END_TEST;
300
301 /* Same as test_sticky_caps_unlinked except that the source pad
302  * has a template of ANY and we will attempt to push
303  * incompatible caps */
304 GST_START_TEST (test_sticky_caps_unlinked_incompatible)
305 {
306   GstCaps *caps, *failcaps;
307   GstPadTemplate *src_template, *sink_template;
308   GstPad *src, *sink;
309   GstEvent *event;
310
311   /* Source pad has ANY caps
312    * Sink pad has foobar caps
313    * We will push the pony express caps (which should fail)
314    */
315   caps = gst_caps_from_string ("foo/bar, dummy=(int){1, 2}");
316   src_template = gst_pad_template_new ("src", GST_PAD_SRC,
317       GST_PAD_ALWAYS, gst_caps_new_any ());
318   sink_template = gst_pad_template_new ("sink", GST_PAD_SINK,
319       GST_PAD_ALWAYS, caps);
320   gst_caps_unref (caps);
321
322   src = gst_pad_new_from_template (src_template, "src");
323   fail_if (src == NULL);
324   sink = gst_pad_new_from_template (sink_template, "sink");
325   fail_if (sink == NULL);
326   gst_pad_set_event_function (sink, sticky_event);
327   gst_pad_set_chain_function (sink, gst_check_chain_func);
328
329   gst_object_unref (src_template);
330   gst_object_unref (sink_template);
331
332   failcaps = gst_caps_from_string ("pony/express, failure=(boolean)true");
333   ASSERT_CAPS_REFCOUNT (failcaps, "caps", 1);
334
335   event = gst_event_new_caps (failcaps);
336   gst_pad_set_active (src, TRUE);
337   /* The pad isn't linked yet, and anything matches the source pad template
338    * (which is ANY) */
339   fail_unless (gst_pad_push_event (src, event) == TRUE);
340   fail_unless (event_caps == NULL);
341
342   /* Linking and activating will not forward the sticky event yet... */
343   fail_unless (GST_PAD_LINK_SUCCESSFUL (gst_pad_link (src, sink)));
344   gst_pad_set_active (sink, TRUE);
345   fail_unless (event_caps == NULL);
346
347   /* ...but the first buffer will and should FAIL since the caps 
348    * are not compatible */
349   fail_unless (gst_pad_push (src,
350           gst_buffer_new ()) == GST_FLOW_NOT_NEGOTIATED);
351   /* We shouldn't have received the caps event since it's incompatible */
352   fail_unless (event_caps == NULL);
353   /* We shouldn't have received any buffers since caps are incompatible */
354   fail_unless_equals_int (g_list_length (buffers), 0);
355
356   gst_caps_replace (&caps, NULL);
357   gst_caps_replace (&event_caps, NULL);
358
359   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
360   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
361   gst_object_unref (src);
362   gst_object_unref (sink);
363 }
364
365 GST_END_TEST;
366
367 /* Like test_sticky_caps_unlinked, but link before caps: */
368
369 GST_START_TEST (test_sticky_caps_flushing)
370 {
371   GstCaps *caps;
372   GstPadTemplate *src_template, *sink_template;
373   GstPad *src, *sink;
374   GstEvent *event;
375
376   caps = gst_caps_from_string ("foo/bar, dummy=(int){1, 2}");
377   src_template = gst_pad_template_new ("src", GST_PAD_SRC,
378       GST_PAD_ALWAYS, caps);
379   sink_template = gst_pad_template_new ("sink", GST_PAD_SINK,
380       GST_PAD_ALWAYS, caps);
381   gst_caps_unref (caps);
382
383   src = gst_pad_new_from_template (src_template, "src");
384   fail_if (src == NULL);
385   sink = gst_pad_new_from_template (sink_template, "sink");
386   fail_if (sink == NULL);
387   gst_pad_set_event_function (sink, sticky_event);
388   gst_pad_set_chain_function (sink, gst_check_chain_func);
389
390   gst_object_unref (src_template);
391   gst_object_unref (sink_template);
392
393   fail_unless (GST_PAD_LINK_SUCCESSFUL (gst_pad_link (src, sink)));
394
395   caps = gst_caps_from_string ("foo/bar, dummy=(int)1");
396   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
397
398   event = gst_event_new_caps (caps);
399   gst_pad_set_active (src, TRUE);
400   /* The caps event gets accepted by the source pad (and stored) */
401   fail_unless (gst_pad_push_event (src, event) == TRUE);
402   /* But wasn't forwarded since the sink pad is flushing (not activated) */
403   fail_unless (event_caps == NULL);
404
405   /* Activating will not forward the sticky event yet... */
406   gst_pad_set_active (sink, TRUE);
407   fail_unless (event_caps == NULL);
408
409   /* ...but the first buffer will: */
410   fail_unless (gst_pad_push (src, gst_buffer_new ()) == GST_FLOW_OK);
411   fail_unless (event_caps == caps);
412   fail_unless_equals_int (g_list_length (buffers), 1);
413
414   gst_caps_replace (&caps, NULL);
415   gst_caps_replace (&event_caps, NULL);
416
417   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
418   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
419   gst_object_unref (src);
420   gst_object_unref (sink);
421 }
422
423 GST_END_TEST;
424
425 static gboolean
426 name_is_valid (const gchar * name, GstPadPresence presence)
427 {
428   GstPadTemplate *new;
429   GstCaps *any = gst_caps_new_any ();
430
431   new = gst_pad_template_new (name, GST_PAD_SRC, presence, any);
432   gst_caps_unref (any);
433   if (new) {
434     gst_object_unref (GST_OBJECT (new));
435     return TRUE;
436   }
437   return FALSE;
438 }
439
440 GST_START_TEST (test_name_is_valid)
441 {
442   gboolean result = FALSE;
443
444   fail_unless (name_is_valid ("src", GST_PAD_ALWAYS));
445   ASSERT_WARNING (name_is_valid ("src%", GST_PAD_ALWAYS));
446   ASSERT_WARNING (result = name_is_valid ("src%d", GST_PAD_ALWAYS));
447   fail_if (result);
448
449   fail_unless (name_is_valid ("src", GST_PAD_REQUEST));
450   ASSERT_WARNING (name_is_valid ("src%s%s", GST_PAD_REQUEST));
451   ASSERT_WARNING (name_is_valid ("src%c", GST_PAD_REQUEST));
452   ASSERT_WARNING (name_is_valid ("src%", GST_PAD_REQUEST));
453   ASSERT_WARNING (name_is_valid ("src%dsrc", GST_PAD_REQUEST));
454
455   fail_unless (name_is_valid ("src", GST_PAD_SOMETIMES));
456   fail_unless (name_is_valid ("src%c", GST_PAD_SOMETIMES));
457 }
458
459 GST_END_TEST;
460
461 static GstPadProbeReturn
462 _probe_handler (GstPad * pad, GstPadProbeInfo * info, gpointer userdata)
463 {
464   gint ret = GPOINTER_TO_INT (userdata);
465
466   if (ret == 1)
467     return GST_PAD_PROBE_OK;
468
469   return GST_PAD_PROBE_DROP;
470 }
471
472 GST_START_TEST (test_push_unlinked)
473 {
474   GstPad *src;
475   GstCaps *caps;
476   GstBuffer *buffer;
477   gulong id;
478
479   src = gst_pad_new ("src", GST_PAD_SRC);
480   fail_if (src == NULL);
481   caps = gst_pad_get_allowed_caps (src);
482   fail_unless (caps == NULL);
483
484   caps = gst_caps_from_string ("foo/bar");
485
486   /* pushing on an inactive pad will return wrong state */
487   GST_DEBUG ("push buffer inactive");
488   buffer = gst_buffer_new ();
489   gst_buffer_ref (buffer);
490   fail_unless (gst_pad_push (src, buffer) == GST_FLOW_WRONG_STATE);
491   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
492   gst_buffer_unref (buffer);
493
494   gst_pad_set_active (src, TRUE);
495   GST_DEBUG ("push caps event inactive");
496   gst_pad_set_caps (src, caps);
497   ASSERT_CAPS_REFCOUNT (caps, "caps", 2);
498
499   /* pushing on an unlinked pad will drop the buffer */
500   GST_DEBUG ("push buffer unlinked");
501   buffer = gst_buffer_new ();
502   gst_buffer_ref (buffer);
503   fail_unless (gst_pad_push (src, buffer) == GST_FLOW_NOT_LINKED);
504   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
505   gst_buffer_unref (buffer);
506
507   /* adding a probe that returns _DROP will drop the buffer without trying
508    * to chain */
509   GST_DEBUG ("push buffer drop");
510   id = gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BUFFER,
511       _probe_handler, GINT_TO_POINTER (0), NULL);
512   buffer = gst_buffer_new ();
513   gst_buffer_ref (buffer);
514   fail_unless (gst_pad_push (src, buffer) == GST_FLOW_OK);
515   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
516   gst_buffer_unref (buffer);
517   gst_pad_remove_probe (src, id);
518
519   /* adding a probe that returns _OK will still chain the buffer,
520    * and hence drop because pad is unlinked */
521   GST_DEBUG ("push buffer ok");
522   id = gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BUFFER,
523       _probe_handler, GINT_TO_POINTER (1), NULL);
524   buffer = gst_buffer_new ();
525   gst_buffer_ref (buffer);
526   fail_unless (gst_pad_push (src, buffer) == GST_FLOW_NOT_LINKED);
527   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
528   gst_buffer_unref (buffer);
529   gst_pad_remove_probe (src, id);
530
531
532   /* cleanup */
533   ASSERT_CAPS_REFCOUNT (caps, "caps", 2);
534   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
535
536   gst_object_unref (src);
537
538   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
539   gst_caps_unref (caps);
540 }
541
542 GST_END_TEST;
543
544 GST_START_TEST (test_push_linked)
545 {
546   GstPad *src, *sink;
547   GstPadLinkReturn plr;
548   GstCaps *caps;
549   GstBuffer *buffer;
550   gulong id;
551
552   /* setup */
553   sink = gst_pad_new ("sink", GST_PAD_SINK);
554   fail_if (sink == NULL);
555   gst_pad_set_chain_function (sink, gst_check_chain_func);
556
557   src = gst_pad_new ("src", GST_PAD_SRC);
558   fail_if (src == NULL);
559
560   caps = gst_caps_from_string ("foo/bar");
561   /* one for me */
562   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
563
564   gst_pad_set_active (src, TRUE);
565   gst_pad_set_caps (src, caps);
566   gst_pad_set_active (sink, TRUE);
567   gst_pad_set_caps (sink, caps);
568   /* one for me and one for each set_caps */
569   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
570
571   plr = gst_pad_link (src, sink);
572   fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
573   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
574
575   buffer = gst_buffer_new ();
576
577   /* test */
578   /* pushing on a linked pad will drop the ref to the buffer */
579   gst_buffer_ref (buffer);
580   fail_unless (gst_pad_push (src, buffer) == GST_FLOW_OK);
581   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 2);
582   gst_buffer_unref (buffer);
583   fail_unless_equals_int (g_list_length (buffers), 1);
584   buffer = GST_BUFFER (buffers->data);
585   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
586   gst_buffer_unref (buffer);
587   g_list_free (buffers);
588   buffers = NULL;
589
590   /* adding a probe that returns FALSE will drop the buffer without trying
591    * to chain */
592   id = gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BUFFER,
593       _probe_handler, GINT_TO_POINTER (0), NULL);
594   buffer = gst_buffer_new ();
595   gst_buffer_ref (buffer);
596   fail_unless (gst_pad_push (src, buffer) == GST_FLOW_OK);
597   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
598   gst_buffer_unref (buffer);
599   gst_pad_remove_probe (src, id);
600   fail_unless_equals_int (g_list_length (buffers), 0);
601
602   /* adding a probe that returns TRUE will still chain the buffer */
603   id = gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BUFFER,
604       _probe_handler, GINT_TO_POINTER (1), NULL);
605   buffer = gst_buffer_new ();
606   gst_buffer_ref (buffer);
607   fail_unless (gst_pad_push (src, buffer) == GST_FLOW_OK);
608   gst_pad_remove_probe (src, id);
609
610   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 2);
611   gst_buffer_unref (buffer);
612   fail_unless_equals_int (g_list_length (buffers), 1);
613   buffer = GST_BUFFER (buffers->data);
614   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
615   gst_buffer_unref (buffer);
616   g_list_free (buffers);
617   buffers = NULL;
618
619   /* teardown */
620   gst_pad_unlink (src, sink);
621   ASSERT_CAPS_REFCOUNT (caps, "caps", 2);
622   gst_object_unref (src);
623   gst_object_unref (sink);
624   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
625
626   gst_caps_unref (caps);
627 }
628
629 GST_END_TEST;
630
631 GST_START_TEST (test_push_linked_flushing)
632 {
633   GstPad *src, *sink;
634   GstCaps *caps;
635   GstPadLinkReturn plr;
636   GstBuffer *buffer;
637   gulong id;
638
639   /* setup */
640   src = gst_pad_new ("src", GST_PAD_SRC);
641   fail_if (src == NULL);
642   sink = gst_pad_new ("sink", GST_PAD_SINK);
643   fail_if (sink == NULL);
644   gst_pad_set_chain_function (sink, gst_check_chain_func);
645
646   caps = gst_pad_get_allowed_caps (src);
647   fail_unless (caps == NULL);
648   caps = gst_pad_get_allowed_caps (sink);
649   fail_unless (caps == NULL);
650
651   caps = gst_caps_from_string ("foo/bar");
652   /* one for me */
653   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
654
655   gst_pad_set_active (src, TRUE);
656   gst_pad_set_caps (src, caps);
657   /* need to activate to make it accept the caps */
658   gst_pad_set_active (sink, TRUE);
659   gst_pad_set_caps (sink, caps);
660   /* one for me and one for each set_caps */
661   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
662
663   plr = gst_pad_link (src, sink);
664   fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
665   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
666
667   /* not activating the pads here, which keeps them flushing */
668   gst_pad_set_active (src, FALSE);
669   gst_pad_set_active (sink, FALSE);
670
671   /* pushing on a flushing pad will drop the buffer */
672   buffer = gst_buffer_new ();
673   gst_buffer_ref (buffer);
674   fail_unless (gst_pad_push (src, buffer) == GST_FLOW_WRONG_STATE);
675   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
676   fail_unless_equals_int (g_list_length (buffers), 0);
677   gst_buffer_unref (buffer);
678
679   gst_pad_set_active (src, TRUE);
680   gst_pad_set_active (sink, FALSE);
681
682   /* adding a probe that returns FALSE will drop the buffer without trying
683    * to chain */
684   id = gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BUFFER, _probe_handler,
685       GINT_TO_POINTER (0), NULL);
686   buffer = gst_buffer_new ();
687   gst_buffer_ref (buffer);
688   fail_unless (gst_pad_push (src, buffer) == GST_FLOW_OK);
689   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
690   fail_unless_equals_int (g_list_length (buffers), 0);
691   gst_buffer_unref (buffer);
692   gst_pad_remove_probe (src, id);
693
694   /* adding a probe that returns TRUE will still chain the buffer,
695    * and hence drop because pad is flushing */
696   id = gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BUFFER, _probe_handler,
697       GINT_TO_POINTER (1), NULL);
698   buffer = gst_buffer_new ();
699   gst_buffer_ref (buffer);
700   fail_unless (gst_pad_push (src, buffer) == GST_FLOW_WRONG_STATE);
701   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
702   fail_unless_equals_int (g_list_length (buffers), 0);
703   gst_buffer_unref (buffer);
704   gst_pad_remove_probe (src, id);
705
706   /* cleanup */
707   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
708   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
709   gst_pad_link (src, sink);
710   gst_object_unref (src);
711   gst_object_unref (sink);
712   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
713   gst_caps_unref (caps);
714 }
715
716 GST_END_TEST;
717
718 static GstBuffer *
719 buffer_from_string (const gchar * str)
720 {
721   guint size;
722   GstBuffer *buf;
723   gpointer data;
724
725   size = strlen (str);
726   buf = gst_buffer_new_and_alloc (size);
727
728   data = gst_buffer_map (buf, NULL, NULL, GST_MAP_WRITE);
729   memcpy (data, str, size);
730   gst_buffer_unmap (buf, data, size);
731
732   return buf;
733 }
734
735 static gboolean
736 buffer_compare (GstBuffer * buf, const gchar * str, gsize size)
737 {
738   gboolean res;
739   gpointer data;
740
741   data = gst_buffer_map (buf, NULL, NULL, GST_MAP_READ);
742   res = memcmp (data, str, size) == 0;
743   GST_DEBUG ("%s <-> %s: %d", (gchar *) data, str, res);
744   gst_buffer_unmap (buf, data, size);
745
746   return res;
747 }
748
749 GST_START_TEST (test_push_buffer_list_compat)
750 {
751   GstPad *src, *sink;
752   GstPadLinkReturn plr;
753   GstCaps *caps;
754   GstBufferList *list;
755   GstBuffer *buffer;
756
757   /* setup */
758   sink = gst_pad_new ("sink", GST_PAD_SINK);
759   fail_if (sink == NULL);
760   gst_pad_set_chain_function (sink, gst_check_chain_func);
761   /* leave chainlistfunc unset */
762
763   src = gst_pad_new ("src", GST_PAD_SRC);
764   fail_if (src == NULL);
765
766   caps = gst_caps_from_string ("foo/bar");
767
768   gst_pad_set_active (src, TRUE);
769   gst_pad_set_caps (src, caps);
770   gst_pad_set_active (sink, TRUE);
771   gst_pad_set_caps (sink, caps);
772
773   plr = gst_pad_link (src, sink);
774   fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
775
776   list = gst_buffer_list_new ();
777
778   /* test */
779   /* adding to a buffer list will drop the ref to the buffer */
780   gst_buffer_list_add (list, buffer_from_string ("ListGroup"));
781   gst_buffer_list_add (list, buffer_from_string ("AnotherListGroup"));
782
783   fail_unless (gst_pad_push_list (src, list) == GST_FLOW_OK);
784   fail_unless_equals_int (g_list_length (buffers), 2);
785   buffer = GST_BUFFER (buffers->data);
786   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
787   fail_unless (buffer_compare (buffer, "ListGroup", 9));
788   gst_buffer_unref (buffer);
789   buffers = g_list_delete_link (buffers, buffers);
790   buffer = GST_BUFFER (buffers->data);
791   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
792   fail_unless (buffer_compare (buffer, "AnotherListGroup", 16));
793   gst_buffer_unref (buffer);
794   buffers = g_list_delete_link (buffers, buffers);
795   fail_unless (buffers == NULL);
796
797   /* teardown */
798   gst_pad_unlink (src, sink);
799   gst_object_unref (src);
800   gst_object_unref (sink);
801   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
802   gst_caps_unref (caps);
803 }
804
805 GST_END_TEST;
806
807 GST_START_TEST (test_flowreturn)
808 {
809   GstFlowReturn ret;
810   GQuark quark;
811
812   /* test some of the macros */
813   ret = GST_FLOW_EOS;
814   fail_if (strcmp (gst_flow_get_name (ret), "eos"));
815   quark = gst_flow_to_quark (ret);
816   fail_if (strcmp (g_quark_to_string (quark), "eos"));
817
818   ret = GST_FLOW_RESEND;
819   fail_if (strcmp (gst_flow_get_name (ret), "resend"));
820   quark = gst_flow_to_quark (ret);
821   fail_if (strcmp (g_quark_to_string (quark), "resend"));
822
823   /* custom returns */
824   ret = GST_FLOW_CUSTOM_SUCCESS;
825   fail_if (strcmp (gst_flow_get_name (ret), "custom-success"));
826   quark = gst_flow_to_quark (ret);
827   fail_if (strcmp (g_quark_to_string (quark), "custom-success"));
828
829   ret = GST_FLOW_CUSTOM_ERROR;
830   fail_if (strcmp (gst_flow_get_name (ret), "custom-error"));
831   quark = gst_flow_to_quark (ret);
832   fail_if (strcmp (g_quark_to_string (quark), "custom-error"));
833
834   /* custom returns clamping */
835   ret = GST_FLOW_CUSTOM_SUCCESS + 2;
836   fail_if (strcmp (gst_flow_get_name (ret), "custom-success"));
837   quark = gst_flow_to_quark (ret);
838   fail_if (strcmp (g_quark_to_string (quark), "custom-success"));
839
840   ret = GST_FLOW_CUSTOM_ERROR - 2;
841   fail_if (strcmp (gst_flow_get_name (ret), "custom-error"));
842   quark = gst_flow_to_quark (ret);
843   fail_if (strcmp (g_quark_to_string (quark), "custom-error"));
844
845   /* unknown values */
846   ret = GST_FLOW_CUSTOM_ERROR + 2;
847   fail_if (strcmp (gst_flow_get_name (ret), "unknown"));
848   quark = gst_flow_to_quark (ret);
849   fail_unless (quark == 0);
850 }
851
852 GST_END_TEST;
853
854 GST_START_TEST (test_push_negotiation)
855 {
856   GstPad *src, *sink;
857   GstPadLinkReturn plr;
858   GstCaps *srccaps =
859       gst_caps_from_string ("audio/x-raw-int,width={16,32},depth={16,32}");
860   GstCaps *sinkcaps =
861       gst_caps_from_string ("audio/x-raw-int,width=32,depth={16,32}");
862   GstPadTemplate *src_template;
863   GstPadTemplate *sink_template;
864   GstCaps *caps;
865
866   /* setup */
867   src_template = gst_pad_template_new ("src", GST_PAD_SRC,
868       GST_PAD_ALWAYS, srccaps);
869   sink_template = gst_pad_template_new ("sink", GST_PAD_SINK,
870       GST_PAD_ALWAYS, sinkcaps);
871   gst_caps_unref (srccaps);
872   gst_caps_unref (sinkcaps);
873
874   sink = gst_pad_new_from_template (sink_template, "sink");
875   fail_if (sink == NULL);
876   gst_pad_set_chain_function (sink, gst_check_chain_func);
877
878   src = gst_pad_new_from_template (src_template, "src");
879   fail_if (src == NULL);
880
881   plr = gst_pad_link (src, sink);
882   fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
883
884   /* activate pads */
885   gst_pad_set_active (src, TRUE);
886   gst_pad_set_active (sink, TRUE);
887
888   caps = gst_caps_from_string ("audio/x-raw-int,width=16,depth=16");
889
890   /* Should fail if src pad caps are incompatible with sink pad caps */
891   gst_pad_set_caps (src, caps);
892   fail_unless (gst_pad_set_caps (sink, caps) == FALSE);
893
894   /* teardown */
895   gst_pad_unlink (src, sink);
896   gst_object_unref (src);
897   gst_object_unref (sink);
898   gst_caps_unref (caps);
899   gst_object_unref (sink_template);
900   gst_object_unref (src_template);
901 }
902
903 GST_END_TEST;
904
905 /* see that an unref also unlinks the pads */
906 GST_START_TEST (test_src_unref_unlink)
907 {
908   GstPad *src, *sink;
909   GstCaps *caps;
910   GstPadLinkReturn plr;
911
912   sink = gst_pad_new ("sink", GST_PAD_SINK);
913   fail_if (sink == NULL);
914
915   src = gst_pad_new ("src", GST_PAD_SRC);
916   fail_if (src == NULL);
917
918   caps = gst_caps_from_string ("foo/bar");
919
920   gst_pad_set_active (src, TRUE);
921   gst_pad_set_caps (src, caps);
922   gst_pad_set_active (sink, TRUE);
923   gst_pad_set_caps (sink, caps);
924
925   plr = gst_pad_link (src, sink);
926   fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
927
928   /* unref the srcpad */
929   gst_object_unref (src);
930
931   /* sink should be unlinked now */
932   fail_if (gst_pad_is_linked (sink));
933
934   /* cleanup */
935   gst_object_unref (sink);
936   gst_caps_unref (caps);
937 }
938
939 GST_END_TEST;
940
941 /* see that an unref also unlinks the pads */
942 GST_START_TEST (test_sink_unref_unlink)
943 {
944   GstPad *src, *sink;
945   GstCaps *caps;
946   GstPadLinkReturn plr;
947
948   sink = gst_pad_new ("sink", GST_PAD_SINK);
949   fail_if (sink == NULL);
950
951   src = gst_pad_new ("src", GST_PAD_SRC);
952   fail_if (src == NULL);
953
954   caps = gst_caps_from_string ("foo/bar");
955
956   gst_pad_set_active (src, TRUE);
957   gst_pad_set_caps (src, caps);
958   gst_pad_set_active (sink, TRUE);
959   gst_pad_set_caps (sink, caps);
960
961   plr = gst_pad_link (src, sink);
962   fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
963
964   /* unref the sinkpad */
965   gst_object_unref (sink);
966
967   /* src should be unlinked now */
968   fail_if (gst_pad_is_linked (src));
969
970   /* cleanup */
971   gst_object_unref (src);
972   gst_caps_unref (caps);
973 }
974
975 GST_END_TEST;
976
977 static gulong id;
978
979 static GstPadProbeReturn
980 block_async_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
981 {
982   gboolean *bool_user_data = (gboolean *) user_data;
983
984   fail_unless ((info->type & GST_PAD_PROBE_TYPE_BLOCK) != 0);
985
986   /* here we should have blocked == 0 unblocked == 0 */
987   fail_unless (bool_user_data[0] == FALSE);
988   fail_unless (bool_user_data[1] == FALSE);
989
990   bool_user_data[0] = TRUE;
991
992   gst_pad_remove_probe (pad, id);
993   bool_user_data[1] = TRUE;
994
995   return GST_PAD_PROBE_OK;
996 }
997
998 GST_START_TEST (test_block_async)
999 {
1000   GstPad *pad;
1001   /* we set data[0] = TRUE when the pad is blocked, data[1] = TRUE when it's
1002    * unblocked */
1003   gboolean data[2] = { FALSE, FALSE };
1004
1005   pad = gst_pad_new ("src", GST_PAD_SRC);
1006   fail_unless (pad != NULL);
1007
1008   gst_pad_set_active (pad, TRUE);
1009   id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BLOCK, block_async_cb, &data,
1010       NULL);
1011
1012   fail_unless (data[0] == FALSE);
1013   fail_unless (data[1] == FALSE);
1014   gst_pad_push (pad, gst_buffer_new ());
1015
1016   gst_object_unref (pad);
1017 }
1018
1019 GST_END_TEST;
1020
1021 static GstPadProbeReturn
1022 block_async_cb_return_ok (GstPad * pad, GstPadProbeInfo * info,
1023     gpointer user_data)
1024 {
1025   return GST_PAD_PROBE_OK;
1026 }
1027
1028 static gpointer
1029 push_buffer_async (GstPad * pad)
1030 {
1031   return GINT_TO_POINTER (gst_pad_push (pad, gst_buffer_new ()));
1032 }
1033
1034 static void
1035 test_pad_blocking_with_type (GstPadProbeType type)
1036 {
1037   GstPad *pad;
1038   GThread *thread;
1039   GstFlowReturn ret;
1040
1041   pad = gst_pad_new ("src", GST_PAD_SRC);
1042   fail_unless (pad != NULL);
1043
1044   gst_pad_set_active (pad, TRUE);
1045   id = gst_pad_add_probe (pad, type, block_async_cb_return_ok, NULL, NULL);
1046
1047
1048   thread = g_thread_create ((GThreadFunc) push_buffer_async, pad, TRUE, NULL);
1049
1050   /* wait for the block */
1051   while (!gst_pad_is_blocking (pad)) {
1052     g_usleep (100000);
1053   }
1054
1055   /* stop with flushing */
1056   gst_pad_push_event (pad, gst_event_new_flush_start ());
1057
1058   /* get return value from push */
1059   ret = GPOINTER_TO_INT (g_thread_join (thread));
1060   /* unflush now */
1061   gst_pad_push_event (pad, gst_event_new_flush_stop (FALSE));
1062   /* must be wrong state */
1063   fail_unless (ret == GST_FLOW_WRONG_STATE);
1064
1065   gst_object_unref (pad);
1066 }
1067
1068 GST_START_TEST (test_pad_blocking_with_probe_type_block)
1069 {
1070   test_pad_blocking_with_type (GST_PAD_PROBE_TYPE_BLOCK);
1071 }
1072
1073 GST_END_TEST;
1074
1075 GST_START_TEST (test_pad_blocking_with_probe_type_blocking)
1076 {
1077   test_pad_blocking_with_type (GST_PAD_PROBE_TYPE_BLOCKING);
1078 }
1079
1080 GST_END_TEST;
1081
1082 #if 0
1083 static void
1084 block_async_second (GstPad * pad, gboolean blocked, gpointer user_data)
1085 {
1086   gst_pad_set_blocked (pad, FALSE, unblock_async_cb, NULL, NULL);
1087 }
1088
1089 static void
1090 block_async_first (GstPad * pad, gboolean blocked, gpointer user_data)
1091 {
1092   static int n_calls = 0;
1093   gboolean *bool_user_data = (gboolean *) user_data;
1094
1095   if (++n_calls > 1)
1096     /* we expect this callback to be called only once */
1097     g_warn_if_reached ();
1098
1099   *bool_user_data = blocked;
1100
1101   /* replace block_async_first with block_async_second so next time the pad is
1102    * blocked the latter should be called */
1103   gst_pad_set_blocked (pad, TRUE, block_async_second, NULL, NULL);
1104
1105   /* unblock temporarily, in the next push block_async_second should be called
1106    */
1107   gst_pad_push_event (pad, gst_event_new_flush_start ());
1108 }
1109
1110 GST_START_TEST (test_block_async_replace_callback)
1111 {
1112   GstPad *pad;
1113   gboolean blocked;
1114
1115   pad = gst_pad_new ("src", GST_PAD_SRC);
1116   fail_unless (pad != NULL);
1117   gst_pad_set_active (pad, TRUE);
1118
1119   gst_pad_set_blocked (pad, TRUE, block_async_first, &blocked, NULL);
1120   blocked = FALSE;
1121
1122   gst_pad_push (pad, gst_buffer_new ());
1123   fail_unless (blocked == TRUE);
1124   /* block_async_first flushes to unblock */
1125   gst_pad_push_event (pad, gst_event_new_flush_stop ());
1126
1127   /* push again, this time block_async_second should be called */
1128   gst_pad_push (pad, gst_buffer_new ());
1129   fail_unless (blocked == TRUE);
1130
1131   gst_object_unref (pad);
1132 }
1133
1134 GST_END_TEST;
1135 #endif
1136
1137 static void
1138 block_async_full_destroy (gpointer user_data)
1139 {
1140   gint *state = (gint *) user_data;
1141
1142   fail_unless (*state < 2);
1143
1144   GST_DEBUG ("setting state to 2");
1145   *state = 2;
1146 }
1147
1148 static GstPadProbeReturn
1149 block_async_full_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
1150 {
1151   *(gint *) user_data = (gint) TRUE;
1152
1153   gst_pad_push_event (pad, gst_event_new_flush_start ());
1154   GST_DEBUG ("setting state to 1");
1155
1156   return GST_PAD_PROBE_OK;
1157 }
1158
1159 GST_START_TEST (test_block_async_full_destroy)
1160 {
1161   GstPad *pad;
1162   /* 0 = unblocked, 1 = blocked, 2 = destroyed */
1163   gint state = 0;
1164   gulong id;
1165
1166   pad = gst_pad_new ("src", GST_PAD_SRC);
1167   fail_unless (pad != NULL);
1168   gst_pad_set_active (pad, TRUE);
1169
1170   id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BLOCK, block_async_full_cb,
1171       &state, block_async_full_destroy);
1172   fail_unless (state == 0);
1173
1174   gst_pad_push (pad, gst_buffer_new ());
1175   /* block_async_full_cb sets state to 1 and then flushes to unblock temporarily
1176    */
1177   fail_unless (state == 1);
1178   gst_pad_push_event (pad, gst_event_new_flush_stop (TRUE));
1179
1180   /* unblock callback is called */
1181   gst_pad_remove_probe (pad, id);
1182   fail_unless (state == 2);
1183
1184   gst_object_unref (pad);
1185 }
1186
1187 GST_END_TEST;
1188
1189 GST_START_TEST (test_block_async_full_destroy_dispose)
1190 {
1191   GstPad *pad;
1192   /* 0 = unblocked, 1 = blocked, 2 = destroyed */
1193   gint state = 0;
1194
1195   pad = gst_pad_new ("src", GST_PAD_SRC);
1196   fail_unless (pad != NULL);
1197   gst_pad_set_active (pad, TRUE);
1198
1199   (void) gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BLOCK, block_async_full_cb,
1200       &state, block_async_full_destroy);
1201
1202   gst_pad_push (pad, gst_buffer_new ());
1203   /* block_async_full_cb sets state to 1 and then flushes to unblock temporarily
1204    */
1205   fail_unless_equals_int (state, 1);
1206   gst_pad_push_event (pad, gst_event_new_flush_stop (TRUE));
1207
1208   /* gst_BLOCK calls the destroy_notify function if necessary */
1209   gst_object_unref (pad);
1210
1211   fail_unless_equals_int (state, 2);
1212 }
1213
1214 GST_END_TEST;
1215
1216
1217 #if 0
1218 static void
1219 unblock_async_no_flush_cb (GstPad * pad, gboolean blocked, gpointer user_data)
1220 {
1221   gboolean *bool_user_data = (gboolean *) user_data;
1222
1223   /* here we should have blocked == 1 unblocked == 0 */
1224
1225   fail_unless (blocked == FALSE);
1226
1227   fail_unless (bool_user_data[0] == TRUE);
1228   fail_unless (bool_user_data[1] == TRUE);
1229   fail_unless (bool_user_data[2] == FALSE);
1230
1231   bool_user_data[2] = TRUE;
1232 }
1233 #endif
1234
1235
1236 #if 0
1237 static void
1238 unblock_async_not_called (GstPad * pad, gboolean blocked, gpointer user_data)
1239 {
1240   g_warn_if_reached ();
1241 }
1242 #endif
1243
1244 static GstPadProbeReturn
1245 block_async_second_no_flush (GstPad * pad, GstPadProbeInfo * info,
1246     gpointer user_data)
1247 {
1248   gboolean *bool_user_data = (gboolean *) user_data;
1249
1250   GST_DEBUG ("second probe called");
1251
1252   fail_unless (info->type & GST_PAD_PROBE_TYPE_BLOCK);
1253
1254   fail_unless (bool_user_data[0] == TRUE);
1255   fail_unless (bool_user_data[1] == FALSE);
1256   fail_unless (bool_user_data[2] == FALSE);
1257
1258   bool_user_data[1] = TRUE;
1259
1260   GST_DEBUG ("removing second probe with id %lu", id);
1261   gst_pad_remove_probe (pad, id);
1262
1263   return GST_PAD_PROBE_OK;
1264 }
1265
1266 static GstPadProbeReturn
1267 block_async_first_no_flush (GstPad * pad, GstPadProbeInfo * info,
1268     gpointer user_data)
1269 {
1270   static int n_calls = 0;
1271   gboolean *bool_user_data = (gboolean *) user_data;
1272
1273   fail_unless (info->type & GST_PAD_PROBE_TYPE_BLOCK);
1274
1275   GST_DEBUG ("first probe called");
1276
1277   if (++n_calls > 1)
1278     /* we expect this callback to be called only once */
1279     g_warn_if_reached ();
1280
1281   *bool_user_data = TRUE;
1282
1283   fail_unless (bool_user_data[0] == TRUE);
1284   fail_unless (bool_user_data[1] == FALSE);
1285   fail_unless (bool_user_data[2] == FALSE);
1286
1287   GST_DEBUG ("removing first probe with id %lu", id);
1288   gst_pad_remove_probe (pad, id);
1289
1290   GST_DEBUG ("adding second probe");
1291   /* replace block_async_first with block_async_second so next time the pad is
1292    * blocked the latter should be called */
1293   id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BLOCK,
1294       block_async_second_no_flush, user_data, NULL);
1295   GST_DEBUG ("added probe with id %lu", id);
1296
1297   return GST_PAD_PROBE_OK;
1298 }
1299
1300 GST_START_TEST (test_block_async_replace_callback_no_flush)
1301 {
1302   GstPad *pad;
1303   gboolean bool_user_data[3] = { FALSE, FALSE, FALSE };
1304
1305   pad = gst_pad_new ("src", GST_PAD_SRC);
1306   fail_unless (pad != NULL);
1307   gst_pad_set_active (pad, TRUE);
1308
1309   GST_DEBUG ("adding probe");
1310   id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BLOCK,
1311       block_async_first_no_flush, bool_user_data, NULL);
1312   GST_DEBUG ("added probe with id %lu", id);
1313   fail_if (id == 0);
1314
1315   GST_DEBUG ("pushing buffer");
1316   gst_pad_push (pad, gst_buffer_new ());
1317   fail_unless (bool_user_data[0] == TRUE);
1318   fail_unless (bool_user_data[1] == TRUE);
1319   fail_unless (bool_user_data[2] == FALSE);
1320
1321   gst_object_unref (pad);
1322 }
1323
1324 GST_END_TEST;
1325
1326
1327 static Suite *
1328 gst_pad_suite (void)
1329 {
1330   Suite *s = suite_create ("GstPad");
1331   TCase *tc_chain = tcase_create ("general");
1332
1333   /* turn off timeout */
1334   tcase_set_timeout (tc_chain, 60);
1335
1336   suite_add_tcase (s, tc_chain);
1337   tcase_add_test (tc_chain, test_link);
1338   tcase_add_test (tc_chain, test_refcount);
1339   tcase_add_test (tc_chain, test_get_allowed_caps);
1340   tcase_add_test (tc_chain, test_sticky_caps_unlinked);
1341   tcase_add_test (tc_chain, test_sticky_caps_unlinked_incompatible);
1342   tcase_add_test (tc_chain, test_sticky_caps_flushing);
1343   tcase_add_test (tc_chain, test_link_unlink_threaded);
1344   tcase_add_test (tc_chain, test_name_is_valid);
1345   tcase_add_test (tc_chain, test_push_unlinked);
1346   tcase_add_test (tc_chain, test_push_linked);
1347   tcase_add_test (tc_chain, test_push_linked_flushing);
1348   tcase_add_test (tc_chain, test_push_buffer_list_compat);
1349   tcase_add_test (tc_chain, test_flowreturn);
1350   tcase_add_test (tc_chain, test_push_negotiation);
1351   tcase_add_test (tc_chain, test_src_unref_unlink);
1352   tcase_add_test (tc_chain, test_sink_unref_unlink);
1353   tcase_add_test (tc_chain, test_block_async);
1354   tcase_add_test (tc_chain, test_pad_blocking_with_probe_type_block);
1355   tcase_add_test (tc_chain, test_pad_blocking_with_probe_type_blocking);
1356 #if 0
1357   tcase_add_test (tc_chain, test_block_async_replace_callback);
1358 #endif
1359   tcase_add_test (tc_chain, test_block_async_full_destroy);
1360   tcase_add_test (tc_chain, test_block_async_full_destroy_dispose);
1361   tcase_add_test (tc_chain, test_block_async_replace_callback_no_flush);
1362
1363   return s;
1364 }
1365
1366 GST_CHECK_MAIN (gst_pad);