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