caps: improve _do_simplify
[platform/upstream/gstreamer.git] / tests / check / gst / gstpad.c
1 /* GStreamer
2  * Copyright (C) <2005> Thomas Vander Stichele <thomas at apestaart dot org>
3  *
4  * gstpad.c: Unit test for GstPad
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 #include <gst/check/gstcheck.h>
23
24 GST_START_TEST (test_link)
25 {
26   GstPad *src, *sink;
27   GstPadTemplate *srct;
28
29   GstPadLinkReturn ret;
30   gchar *name;
31
32   src = gst_pad_new ("source", GST_PAD_SRC);
33   fail_if (src == NULL);
34   ASSERT_OBJECT_REFCOUNT (src, "source pad", 1);
35
36   name = gst_pad_get_name (src);
37   fail_unless (strcmp (name, "source") == 0);
38   ASSERT_OBJECT_REFCOUNT (src, "source pad", 1);
39   g_free (name);
40
41   sink = gst_pad_new ("sink", GST_PAD_SINK);
42   fail_if (sink == NULL);
43
44   /* linking without templates or caps should 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_create ((GThreadFunc) push_buffer_async, pad, TRUE, NULL);
1042
1043   /* wait for the block */
1044   while (!gst_pad_is_blocking (pad)) {
1045     g_usleep (100000);
1046   }
1047
1048   /* stop with flushing */
1049   gst_pad_push_event (pad, gst_event_new_flush_start ());
1050
1051   /* get return value from push */
1052   ret = GPOINTER_TO_INT (g_thread_join (thread));
1053   /* unflush now */
1054   gst_pad_push_event (pad, gst_event_new_flush_stop (FALSE));
1055   /* must be wrong state */
1056   fail_unless (ret == GST_FLOW_FLUSHING);
1057
1058   gst_object_unref (pad);
1059 }
1060
1061 GST_START_TEST (test_pad_blocking_with_probe_type_block)
1062 {
1063   test_pad_blocking_with_type (GST_PAD_PROBE_TYPE_BLOCK);
1064 }
1065
1066 GST_END_TEST;
1067
1068 GST_START_TEST (test_pad_blocking_with_probe_type_blocking)
1069 {
1070   test_pad_blocking_with_type (GST_PAD_PROBE_TYPE_BLOCKING);
1071 }
1072
1073 GST_END_TEST;
1074
1075 static gboolean got_notify;
1076
1077 static void
1078 caps_notify (GstPad * pad, GParamSpec * spec, gpointer data)
1079 {
1080   got_notify = TRUE;
1081 }
1082
1083 static void
1084 test_queue_src_caps_notify (gboolean link_queue)
1085 {
1086   GstElement *queue;
1087   GstPad *src, *sink, *another_pad;
1088
1089   queue = gst_element_factory_make ("queue", NULL);
1090   fail_unless (queue != NULL);
1091
1092   src = gst_element_get_static_pad (queue, "src");
1093   fail_unless (src != NULL);
1094
1095   sink = gst_element_get_static_pad (queue, "sink");
1096   fail_unless (sink != NULL);
1097
1098   if (link_queue) {
1099     another_pad = gst_pad_new ("sink", GST_PAD_SINK);
1100     fail_unless (another_pad != NULL);
1101     gst_pad_set_active (another_pad, TRUE);
1102
1103     gst_pad_link_full (src, another_pad, GST_PAD_LINK_CHECK_NOTHING);
1104   } else {
1105     another_pad = NULL;
1106   }
1107
1108   gst_element_set_state (queue, GST_STATE_PLAYING);
1109
1110   got_notify = FALSE;
1111
1112   g_signal_connect (src, "notify::caps", G_CALLBACK (caps_notify), NULL);
1113
1114   gst_pad_send_event (sink, gst_event_new_caps (gst_caps_from_string ("caps")));
1115
1116   g_usleep (10000);
1117
1118   fail_unless (got_notify == TRUE);
1119
1120   gst_element_set_state (queue, GST_STATE_NULL);
1121
1122   gst_object_unref (src);
1123   gst_object_unref (sink);
1124   gst_object_unref (queue);
1125   if (another_pad) {
1126     gst_object_unref (another_pad);
1127   }
1128 }
1129
1130 GST_START_TEST (test_queue_src_caps_notify_linked)
1131 {
1132   test_queue_src_caps_notify (TRUE);
1133 }
1134
1135 GST_END_TEST
1136 GST_START_TEST (test_queue_src_caps_notify_not_linked)
1137 {
1138   /* This test will fail because queue doesn't set the caps
1139      on src pad unless it is linked */
1140   test_queue_src_caps_notify (FALSE);
1141 }
1142
1143 GST_END_TEST;
1144
1145 #if 0
1146 static void
1147 block_async_second (GstPad * pad, gboolean blocked, gpointer user_data)
1148 {
1149   gst_pad_set_blocked (pad, FALSE, unblock_async_cb, NULL, NULL);
1150 }
1151
1152 static void
1153 block_async_first (GstPad * pad, gboolean blocked, gpointer user_data)
1154 {
1155   static int n_calls = 0;
1156   gboolean *bool_user_data = (gboolean *) user_data;
1157
1158   if (++n_calls > 1)
1159     /* we expect this callback to be called only once */
1160     g_warn_if_reached ();
1161
1162   *bool_user_data = blocked;
1163
1164   /* replace block_async_first with block_async_second so next time the pad is
1165    * blocked the latter should be called */
1166   gst_pad_set_blocked (pad, TRUE, block_async_second, NULL, NULL);
1167
1168   /* unblock temporarily, in the next push block_async_second should be called
1169    */
1170   gst_pad_push_event (pad, gst_event_new_flush_start ());
1171 }
1172
1173 GST_START_TEST (test_block_async_replace_callback)
1174 {
1175   GstPad *pad;
1176   gboolean blocked;
1177
1178   pad = gst_pad_new ("src", GST_PAD_SRC);
1179   fail_unless (pad != NULL);
1180   gst_pad_set_active (pad, TRUE);
1181
1182   gst_pad_set_blocked (pad, TRUE, block_async_first, &blocked, NULL);
1183   blocked = FALSE;
1184
1185   gst_pad_push (pad, gst_buffer_new ());
1186   fail_unless (blocked == TRUE);
1187   /* block_async_first flushes to unblock */
1188   gst_pad_push_event (pad, gst_event_new_flush_stop ());
1189
1190   /* push again, this time block_async_second should be called */
1191   gst_pad_push (pad, gst_buffer_new ());
1192   fail_unless (blocked == TRUE);
1193
1194   gst_object_unref (pad);
1195 }
1196
1197 GST_END_TEST;
1198 #endif
1199
1200 static void
1201 block_async_full_destroy (gpointer user_data)
1202 {
1203   gint *state = (gint *) user_data;
1204
1205   fail_unless (*state < 2);
1206
1207   GST_DEBUG ("setting state to 2");
1208   *state = 2;
1209 }
1210
1211 static GstPadProbeReturn
1212 block_async_full_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
1213 {
1214   *(gint *) user_data = (gint) TRUE;
1215
1216   gst_pad_push_event (pad, gst_event_new_flush_start ());
1217   GST_DEBUG ("setting state to 1");
1218
1219   return GST_PAD_PROBE_OK;
1220 }
1221
1222 GST_START_TEST (test_block_async_full_destroy)
1223 {
1224   GstPad *pad;
1225   /* 0 = unblocked, 1 = blocked, 2 = destroyed */
1226   gint state = 0;
1227   gulong id;
1228
1229   pad = gst_pad_new ("src", GST_PAD_SRC);
1230   fail_unless (pad != NULL);
1231   gst_pad_set_active (pad, TRUE);
1232
1233   id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BLOCK, block_async_full_cb,
1234       &state, block_async_full_destroy);
1235   fail_unless (state == 0);
1236
1237   gst_pad_push (pad, gst_buffer_new ());
1238   /* block_async_full_cb sets state to 1 and then flushes to unblock temporarily
1239    */
1240   fail_unless (state == 1);
1241   gst_pad_push_event (pad, gst_event_new_flush_stop (TRUE));
1242
1243   /* unblock callback is called */
1244   gst_pad_remove_probe (pad, id);
1245   fail_unless (state == 2);
1246
1247   gst_object_unref (pad);
1248 }
1249
1250 GST_END_TEST;
1251
1252 GST_START_TEST (test_block_async_full_destroy_dispose)
1253 {
1254   GstPad *pad;
1255   /* 0 = unblocked, 1 = blocked, 2 = destroyed */
1256   gint state = 0;
1257
1258   pad = gst_pad_new ("src", GST_PAD_SRC);
1259   fail_unless (pad != NULL);
1260   gst_pad_set_active (pad, TRUE);
1261
1262   (void) gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BLOCK, block_async_full_cb,
1263       &state, block_async_full_destroy);
1264
1265   gst_pad_push (pad, gst_buffer_new ());
1266   /* block_async_full_cb sets state to 1 and then flushes to unblock temporarily
1267    */
1268   fail_unless_equals_int (state, 1);
1269   gst_pad_push_event (pad, gst_event_new_flush_stop (TRUE));
1270
1271   /* gst_BLOCK calls the destroy_notify function if necessary */
1272   gst_object_unref (pad);
1273
1274   fail_unless_equals_int (state, 2);
1275 }
1276
1277 GST_END_TEST;
1278
1279
1280 #if 0
1281 static void
1282 unblock_async_no_flush_cb (GstPad * pad, gboolean blocked, gpointer user_data)
1283 {
1284   gboolean *bool_user_data = (gboolean *) user_data;
1285
1286   /* here we should have blocked == 1 unblocked == 0 */
1287
1288   fail_unless (blocked == FALSE);
1289
1290   fail_unless (bool_user_data[0] == TRUE);
1291   fail_unless (bool_user_data[1] == TRUE);
1292   fail_unless (bool_user_data[2] == FALSE);
1293
1294   bool_user_data[2] = TRUE;
1295 }
1296 #endif
1297
1298
1299 #if 0
1300 static void
1301 unblock_async_not_called (GstPad * pad, gboolean blocked, gpointer user_data)
1302 {
1303   g_warn_if_reached ();
1304 }
1305 #endif
1306
1307 static GstPadProbeReturn
1308 block_async_second_no_flush (GstPad * pad, GstPadProbeInfo * info,
1309     gpointer user_data)
1310 {
1311   gboolean *bool_user_data = (gboolean *) user_data;
1312
1313   GST_DEBUG ("second probe called");
1314
1315   fail_unless (info->type & GST_PAD_PROBE_TYPE_BLOCK);
1316
1317   fail_unless (bool_user_data[0] == TRUE);
1318   fail_unless (bool_user_data[1] == FALSE);
1319   fail_unless (bool_user_data[2] == FALSE);
1320
1321   bool_user_data[1] = TRUE;
1322
1323   GST_DEBUG ("removing second probe with id %lu", id);
1324   gst_pad_remove_probe (pad, id);
1325
1326   return GST_PAD_PROBE_OK;
1327 }
1328
1329 static GstPadProbeReturn
1330 block_async_first_no_flush (GstPad * pad, GstPadProbeInfo * info,
1331     gpointer user_data)
1332 {
1333   static int n_calls = 0;
1334   gboolean *bool_user_data = (gboolean *) user_data;
1335
1336   fail_unless (info->type & GST_PAD_PROBE_TYPE_BLOCK);
1337
1338   GST_DEBUG ("first probe called");
1339
1340   if (++n_calls > 1)
1341     /* we expect this callback to be called only once */
1342     g_warn_if_reached ();
1343
1344   *bool_user_data = TRUE;
1345
1346   fail_unless (bool_user_data[0] == TRUE);
1347   fail_unless (bool_user_data[1] == FALSE);
1348   fail_unless (bool_user_data[2] == FALSE);
1349
1350   GST_DEBUG ("removing first probe with id %lu", id);
1351   gst_pad_remove_probe (pad, id);
1352
1353   GST_DEBUG ("adding second probe");
1354   /* replace block_async_first with block_async_second so next time the pad is
1355    * blocked the latter should be called */
1356   id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BLOCK,
1357       block_async_second_no_flush, user_data, NULL);
1358   GST_DEBUG ("added probe with id %lu", id);
1359
1360   return GST_PAD_PROBE_OK;
1361 }
1362
1363 GST_START_TEST (test_block_async_replace_callback_no_flush)
1364 {
1365   GstPad *pad;
1366   gboolean bool_user_data[3] = { FALSE, FALSE, FALSE };
1367
1368   pad = gst_pad_new ("src", GST_PAD_SRC);
1369   fail_unless (pad != NULL);
1370   gst_pad_set_active (pad, TRUE);
1371
1372   GST_DEBUG ("adding probe");
1373   id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BLOCK,
1374       block_async_first_no_flush, bool_user_data, NULL);
1375   GST_DEBUG ("added probe with id %lu", id);
1376   fail_if (id == 0);
1377
1378   GST_DEBUG ("pushing buffer");
1379   gst_pad_push (pad, gst_buffer_new ());
1380   fail_unless (bool_user_data[0] == TRUE);
1381   fail_unless (bool_user_data[1] == TRUE);
1382   fail_unless (bool_user_data[2] == FALSE);
1383
1384   gst_object_unref (pad);
1385 }
1386
1387 GST_END_TEST;
1388
1389 static gint sticky_count;
1390
1391 static gboolean
1392 test_sticky_events_handler (GstPad * pad, GstObject * parent, GstEvent * event)
1393 {
1394   GST_DEBUG_OBJECT (pad, "received event %" GST_PTR_FORMAT, event);
1395
1396   switch (sticky_count) {
1397     case 0:
1398       fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_STREAM_START);
1399       break;
1400     case 1:
1401     {
1402       GstCaps *caps;
1403       GstStructure *s;
1404
1405       fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_CAPS);
1406
1407       gst_event_parse_caps (event, &caps);
1408       fail_unless (gst_caps_get_size (caps) == 1);
1409       s = gst_caps_get_structure (caps, 0);
1410       fail_unless (gst_structure_has_name (s, "foo/baz"));
1411       break;
1412     }
1413     case 2:
1414       fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT);
1415       break;
1416     default:
1417       fail_unless (FALSE);
1418       break;
1419   }
1420
1421   gst_event_unref (event);
1422   sticky_count++;
1423
1424   return TRUE;
1425 }
1426
1427 GST_START_TEST (test_sticky_events)
1428 {
1429   GstPad *srcpad, *sinkpad;
1430   GstCaps *caps;
1431   GstSegment seg;
1432
1433   /* make unlinked srcpad */
1434   srcpad = gst_pad_new ("src", GST_PAD_SRC);
1435   fail_unless (srcpad != NULL);
1436   gst_pad_set_active (srcpad, TRUE);
1437
1438   /* push an event, it should be sticky on the srcpad */
1439   gst_pad_push_event (srcpad, gst_event_new_stream_start ());
1440
1441   /* make a caps event */
1442   caps = gst_caps_new_empty_simple ("foo/bar");
1443   gst_pad_push_event (srcpad, gst_event_new_caps (caps));
1444   gst_caps_unref (caps);
1445
1446   /* make segment event */
1447   gst_segment_init (&seg, GST_FORMAT_TIME);
1448   gst_pad_push_event (srcpad, gst_event_new_segment (&seg));
1449
1450   /* now make a sinkpad */
1451   sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
1452   fail_unless (sinkpad != NULL);
1453   sticky_count = 0;
1454   gst_pad_set_event_function (sinkpad, test_sticky_events_handler);
1455   fail_unless (sticky_count == 0);
1456   gst_pad_set_active (sinkpad, TRUE);
1457
1458   /* link the pads */
1459   gst_pad_link (srcpad, sinkpad);
1460   /* should not trigger events */
1461   fail_unless (sticky_count == 0);
1462
1463   /* caps replaces old caps event at position 2, the pushes all
1464    * pending events */
1465   caps = gst_caps_new_empty_simple ("foo/baz");
1466   gst_pad_push_event (srcpad, gst_event_new_caps (caps));
1467   gst_caps_unref (caps);
1468
1469   /* should have triggered 2 events */
1470   fail_unless (sticky_count == 3);
1471
1472   gst_object_unref (srcpad);
1473   gst_object_unref (sinkpad);
1474 }
1475
1476 GST_END_TEST;
1477
1478 static Suite *
1479 gst_pad_suite (void)
1480 {
1481   Suite *s = suite_create ("GstPad");
1482   TCase *tc_chain = tcase_create ("general");
1483
1484   /* turn off timeout */
1485   tcase_set_timeout (tc_chain, 60);
1486
1487   suite_add_tcase (s, tc_chain);
1488   tcase_add_test (tc_chain, test_link);
1489   tcase_add_test (tc_chain, test_refcount);
1490   tcase_add_test (tc_chain, test_get_allowed_caps);
1491   tcase_add_test (tc_chain, test_sticky_caps_unlinked);
1492   tcase_add_test (tc_chain, test_sticky_caps_unlinked_incompatible);
1493   tcase_add_test (tc_chain, test_sticky_caps_flushing);
1494   tcase_add_test (tc_chain, test_link_unlink_threaded);
1495   tcase_add_test (tc_chain, test_name_is_valid);
1496   tcase_add_test (tc_chain, test_push_unlinked);
1497   tcase_add_test (tc_chain, test_push_linked);
1498   tcase_add_test (tc_chain, test_push_linked_flushing);
1499   tcase_add_test (tc_chain, test_push_buffer_list_compat);
1500   tcase_add_test (tc_chain, test_flowreturn);
1501   tcase_add_test (tc_chain, test_push_negotiation);
1502   tcase_add_test (tc_chain, test_src_unref_unlink);
1503   tcase_add_test (tc_chain, test_sink_unref_unlink);
1504   tcase_add_test (tc_chain, test_block_async);
1505   tcase_add_test (tc_chain, test_pad_blocking_with_probe_type_block);
1506   tcase_add_test (tc_chain, test_pad_blocking_with_probe_type_blocking);
1507   tcase_add_test (tc_chain, test_queue_src_caps_notify_linked);
1508   tcase_add_test (tc_chain, test_queue_src_caps_notify_not_linked);
1509 #if 0
1510   tcase_add_test (tc_chain, test_block_async_replace_callback);
1511 #endif
1512   tcase_add_test (tc_chain, test_block_async_full_destroy);
1513   tcase_add_test (tc_chain, test_block_async_full_destroy_dispose);
1514   tcase_add_test (tc_chain, test_block_async_replace_callback_no_flush);
1515   tcase_add_test (tc_chain, test_sticky_events);
1516
1517   return s;
1518 }
1519
1520 GST_CHECK_MAIN (gst_pad);