event: Update for stream-start event API changes
[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 (10000);
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   GstCaps *caps;
1089
1090   queue = gst_element_factory_make ("queue", NULL);
1091   fail_unless (queue != NULL);
1092
1093   src = gst_element_get_static_pad (queue, "src");
1094   fail_unless (src != NULL);
1095
1096   sink = gst_element_get_static_pad (queue, "sink");
1097   fail_unless (sink != NULL);
1098
1099   if (link_queue) {
1100     another_pad = gst_pad_new ("sink", GST_PAD_SINK);
1101     fail_unless (another_pad != NULL);
1102     gst_pad_set_active (another_pad, TRUE);
1103
1104     gst_pad_link_full (src, another_pad, GST_PAD_LINK_CHECK_NOTHING);
1105   } else {
1106     another_pad = NULL;
1107   }
1108
1109   gst_element_set_state (queue, GST_STATE_PLAYING);
1110
1111   got_notify = FALSE;
1112
1113   g_signal_connect (src, "notify::caps", G_CALLBACK (caps_notify), NULL);
1114
1115   caps = gst_caps_from_string ("caps");
1116   gst_pad_send_event (sink, gst_event_new_caps (caps));
1117   gst_caps_unref (caps);
1118
1119   while (got_notify == FALSE)
1120     g_usleep (10000);
1121
1122   gst_element_set_state (queue, GST_STATE_NULL);
1123
1124   gst_object_unref (src);
1125   gst_object_unref (sink);
1126   gst_object_unref (queue);
1127   if (another_pad) {
1128     gst_object_unref (another_pad);
1129   }
1130 }
1131
1132 GST_START_TEST (test_queue_src_caps_notify_linked)
1133 {
1134   test_queue_src_caps_notify (TRUE);
1135 }
1136
1137 GST_END_TEST
1138 GST_START_TEST (test_queue_src_caps_notify_not_linked)
1139 {
1140   /* This test will fail because queue doesn't set the caps
1141      on src pad unless it is linked */
1142   test_queue_src_caps_notify (FALSE);
1143 }
1144
1145 GST_END_TEST;
1146
1147 #if 0
1148 static void
1149 block_async_second (GstPad * pad, gboolean blocked, gpointer user_data)
1150 {
1151   gst_pad_set_blocked (pad, FALSE, unblock_async_cb, NULL, NULL);
1152 }
1153
1154 static void
1155 block_async_first (GstPad * pad, gboolean blocked, gpointer user_data)
1156 {
1157   static int n_calls = 0;
1158   gboolean *bool_user_data = (gboolean *) user_data;
1159
1160   if (++n_calls > 1)
1161     /* we expect this callback to be called only once */
1162     g_warn_if_reached ();
1163
1164   *bool_user_data = blocked;
1165
1166   /* replace block_async_first with block_async_second so next time the pad is
1167    * blocked the latter should be called */
1168   gst_pad_set_blocked (pad, TRUE, block_async_second, NULL, NULL);
1169
1170   /* unblock temporarily, in the next push block_async_second should be called
1171    */
1172   gst_pad_push_event (pad, gst_event_new_flush_start ());
1173 }
1174
1175 GST_START_TEST (test_block_async_replace_callback)
1176 {
1177   GstPad *pad;
1178   gboolean blocked;
1179
1180   pad = gst_pad_new ("src", GST_PAD_SRC);
1181   fail_unless (pad != NULL);
1182   gst_pad_set_active (pad, TRUE);
1183
1184   gst_pad_set_blocked (pad, TRUE, block_async_first, &blocked, NULL);
1185   blocked = FALSE;
1186
1187   gst_pad_push (pad, gst_buffer_new ());
1188   fail_unless (blocked == TRUE);
1189   /* block_async_first flushes to unblock */
1190   gst_pad_push_event (pad, gst_event_new_flush_stop ());
1191
1192   /* push again, this time block_async_second should be called */
1193   gst_pad_push (pad, gst_buffer_new ());
1194   fail_unless (blocked == TRUE);
1195
1196   gst_object_unref (pad);
1197 }
1198
1199 GST_END_TEST;
1200 #endif
1201
1202 static void
1203 block_async_full_destroy (gpointer user_data)
1204 {
1205   gint *state = (gint *) user_data;
1206
1207   fail_unless (*state < 2);
1208
1209   GST_DEBUG ("setting state to 2");
1210   *state = 2;
1211 }
1212
1213 static GstPadProbeReturn
1214 block_async_full_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
1215 {
1216   *(gint *) user_data = (gint) TRUE;
1217
1218   gst_pad_push_event (pad, gst_event_new_flush_start ());
1219   GST_DEBUG ("setting state to 1");
1220
1221   return GST_PAD_PROBE_OK;
1222 }
1223
1224 GST_START_TEST (test_block_async_full_destroy)
1225 {
1226   GstPad *pad;
1227   /* 0 = unblocked, 1 = blocked, 2 = destroyed */
1228   gint state = 0;
1229   gulong id;
1230
1231   pad = gst_pad_new ("src", GST_PAD_SRC);
1232   fail_unless (pad != NULL);
1233   gst_pad_set_active (pad, TRUE);
1234
1235   id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BLOCK, block_async_full_cb,
1236       &state, block_async_full_destroy);
1237   fail_unless (state == 0);
1238
1239   gst_pad_push (pad, gst_buffer_new ());
1240   /* block_async_full_cb sets state to 1 and then flushes to unblock temporarily
1241    */
1242   fail_unless (state == 1);
1243   gst_pad_push_event (pad, gst_event_new_flush_stop (TRUE));
1244
1245   /* unblock callback is called */
1246   gst_pad_remove_probe (pad, id);
1247   fail_unless (state == 2);
1248
1249   gst_object_unref (pad);
1250 }
1251
1252 GST_END_TEST;
1253
1254 GST_START_TEST (test_block_async_full_destroy_dispose)
1255 {
1256   GstPad *pad;
1257   /* 0 = unblocked, 1 = blocked, 2 = destroyed */
1258   gint state = 0;
1259
1260   pad = gst_pad_new ("src", GST_PAD_SRC);
1261   fail_unless (pad != NULL);
1262   gst_pad_set_active (pad, TRUE);
1263
1264   (void) gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BLOCK, block_async_full_cb,
1265       &state, block_async_full_destroy);
1266
1267   gst_pad_push (pad, gst_buffer_new ());
1268   /* block_async_full_cb sets state to 1 and then flushes to unblock temporarily
1269    */
1270   fail_unless_equals_int (state, 1);
1271   gst_pad_push_event (pad, gst_event_new_flush_stop (TRUE));
1272
1273   /* gst_BLOCK calls the destroy_notify function if necessary */
1274   gst_object_unref (pad);
1275
1276   fail_unless_equals_int (state, 2);
1277 }
1278
1279 GST_END_TEST;
1280
1281
1282 #if 0
1283 static void
1284 unblock_async_no_flush_cb (GstPad * pad, gboolean blocked, gpointer user_data)
1285 {
1286   gboolean *bool_user_data = (gboolean *) user_data;
1287
1288   /* here we should have blocked == 1 unblocked == 0 */
1289
1290   fail_unless (blocked == FALSE);
1291
1292   fail_unless (bool_user_data[0] == TRUE);
1293   fail_unless (bool_user_data[1] == TRUE);
1294   fail_unless (bool_user_data[2] == FALSE);
1295
1296   bool_user_data[2] = TRUE;
1297 }
1298 #endif
1299
1300
1301 #if 0
1302 static void
1303 unblock_async_not_called (GstPad * pad, gboolean blocked, gpointer user_data)
1304 {
1305   g_warn_if_reached ();
1306 }
1307 #endif
1308
1309 static GstPadProbeReturn
1310 block_async_second_no_flush (GstPad * pad, GstPadProbeInfo * info,
1311     gpointer user_data)
1312 {
1313   gboolean *bool_user_data = (gboolean *) user_data;
1314
1315   GST_DEBUG ("second probe called");
1316
1317   fail_unless (info->type & GST_PAD_PROBE_TYPE_BLOCK);
1318
1319   fail_unless (bool_user_data[0] == TRUE);
1320   fail_unless (bool_user_data[1] == FALSE);
1321   fail_unless (bool_user_data[2] == FALSE);
1322
1323   bool_user_data[1] = TRUE;
1324
1325   GST_DEBUG ("removing second probe with id %lu", id);
1326   gst_pad_remove_probe (pad, id);
1327
1328   return GST_PAD_PROBE_OK;
1329 }
1330
1331 static GstPadProbeReturn
1332 block_async_first_no_flush (GstPad * pad, GstPadProbeInfo * info,
1333     gpointer user_data)
1334 {
1335   static int n_calls = 0;
1336   gboolean *bool_user_data = (gboolean *) user_data;
1337
1338   fail_unless (info->type & GST_PAD_PROBE_TYPE_BLOCK);
1339
1340   GST_DEBUG ("first probe called");
1341
1342   if (++n_calls > 1)
1343     /* we expect this callback to be called only once */
1344     g_warn_if_reached ();
1345
1346   *bool_user_data = TRUE;
1347
1348   fail_unless (bool_user_data[0] == TRUE);
1349   fail_unless (bool_user_data[1] == FALSE);
1350   fail_unless (bool_user_data[2] == FALSE);
1351
1352   GST_DEBUG ("removing first probe with id %lu", id);
1353   gst_pad_remove_probe (pad, id);
1354
1355   GST_DEBUG ("adding second probe");
1356   /* replace block_async_first with block_async_second so next time the pad is
1357    * blocked the latter should be called */
1358   id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BLOCK,
1359       block_async_second_no_flush, user_data, NULL);
1360   GST_DEBUG ("added probe with id %lu", id);
1361
1362   return GST_PAD_PROBE_OK;
1363 }
1364
1365 GST_START_TEST (test_block_async_replace_callback_no_flush)
1366 {
1367   GstPad *pad;
1368   gboolean bool_user_data[3] = { FALSE, FALSE, FALSE };
1369
1370   pad = gst_pad_new ("src", GST_PAD_SRC);
1371   fail_unless (pad != NULL);
1372   gst_pad_set_active (pad, TRUE);
1373
1374   GST_DEBUG ("adding probe");
1375   id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BLOCK,
1376       block_async_first_no_flush, bool_user_data, NULL);
1377   GST_DEBUG ("added probe with id %lu", id);
1378   fail_if (id == 0);
1379
1380   GST_DEBUG ("pushing buffer");
1381   gst_pad_push (pad, gst_buffer_new ());
1382   fail_unless (bool_user_data[0] == TRUE);
1383   fail_unless (bool_user_data[1] == TRUE);
1384   fail_unless (bool_user_data[2] == FALSE);
1385
1386   gst_object_unref (pad);
1387 }
1388
1389 GST_END_TEST;
1390
1391 static gint sticky_count;
1392
1393 static gboolean
1394 test_sticky_events_handler (GstPad * pad, GstObject * parent, GstEvent * event)
1395 {
1396   GST_DEBUG_OBJECT (pad, "received event %" GST_PTR_FORMAT, event);
1397
1398   switch (sticky_count) {
1399     case 0:
1400       fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_STREAM_START);
1401       break;
1402     case 1:
1403     {
1404       GstCaps *caps;
1405       GstStructure *s;
1406
1407       fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_CAPS);
1408
1409       gst_event_parse_caps (event, &caps);
1410       fail_unless (gst_caps_get_size (caps) == 1);
1411       s = gst_caps_get_structure (caps, 0);
1412       fail_unless (gst_structure_has_name (s, "foo/baz"));
1413       break;
1414     }
1415     case 2:
1416       fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT);
1417       break;
1418     default:
1419       fail_unless (FALSE);
1420       break;
1421   }
1422
1423   gst_event_unref (event);
1424   sticky_count++;
1425
1426   return TRUE;
1427 }
1428
1429 GST_START_TEST (test_sticky_events)
1430 {
1431   GstPad *srcpad, *sinkpad;
1432   GstCaps *caps;
1433   GstSegment seg;
1434
1435   /* make unlinked srcpad */
1436   srcpad = gst_pad_new ("src", GST_PAD_SRC);
1437   fail_unless (srcpad != NULL);
1438   gst_pad_set_active (srcpad, TRUE);
1439
1440   /* push an event, it should be sticky on the srcpad */
1441   gst_pad_push_event (srcpad, gst_event_new_stream_start ("test"));
1442
1443   /* make a caps event */
1444   caps = gst_caps_new_empty_simple ("foo/bar");
1445   gst_pad_push_event (srcpad, gst_event_new_caps (caps));
1446   gst_caps_unref (caps);
1447
1448   /* make segment event */
1449   gst_segment_init (&seg, GST_FORMAT_TIME);
1450   gst_pad_push_event (srcpad, gst_event_new_segment (&seg));
1451
1452   /* now make a sinkpad */
1453   sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
1454   fail_unless (sinkpad != NULL);
1455   sticky_count = 0;
1456   gst_pad_set_event_function (sinkpad, test_sticky_events_handler);
1457   fail_unless (sticky_count == 0);
1458   gst_pad_set_active (sinkpad, TRUE);
1459
1460   /* link the pads */
1461   gst_pad_link (srcpad, sinkpad);
1462   /* should not trigger events */
1463   fail_unless (sticky_count == 0);
1464
1465   /* caps replaces old caps event at position 2, the pushes all
1466    * pending events */
1467   caps = gst_caps_new_empty_simple ("foo/baz");
1468   gst_pad_push_event (srcpad, gst_event_new_caps (caps));
1469   gst_caps_unref (caps);
1470
1471   /* should have triggered 2 events */
1472   fail_unless (sticky_count == 3);
1473
1474   gst_object_unref (srcpad);
1475   gst_object_unref (sinkpad);
1476 }
1477
1478 GST_END_TEST;
1479
1480 static Suite *
1481 gst_pad_suite (void)
1482 {
1483   Suite *s = suite_create ("GstPad");
1484   TCase *tc_chain = tcase_create ("general");
1485
1486   /* turn off timeout */
1487   tcase_set_timeout (tc_chain, 60);
1488
1489   suite_add_tcase (s, tc_chain);
1490   tcase_add_test (tc_chain, test_link);
1491   tcase_add_test (tc_chain, test_refcount);
1492   tcase_add_test (tc_chain, test_get_allowed_caps);
1493   tcase_add_test (tc_chain, test_sticky_caps_unlinked);
1494   tcase_add_test (tc_chain, test_sticky_caps_unlinked_incompatible);
1495   tcase_add_test (tc_chain, test_sticky_caps_flushing);
1496   tcase_add_test (tc_chain, test_link_unlink_threaded);
1497   tcase_add_test (tc_chain, test_name_is_valid);
1498   tcase_add_test (tc_chain, test_push_unlinked);
1499   tcase_add_test (tc_chain, test_push_linked);
1500   tcase_add_test (tc_chain, test_push_linked_flushing);
1501   tcase_add_test (tc_chain, test_push_buffer_list_compat);
1502   tcase_add_test (tc_chain, test_flowreturn);
1503   tcase_add_test (tc_chain, test_push_negotiation);
1504   tcase_add_test (tc_chain, test_src_unref_unlink);
1505   tcase_add_test (tc_chain, test_sink_unref_unlink);
1506   tcase_add_test (tc_chain, test_block_async);
1507   tcase_add_test (tc_chain, test_pad_blocking_with_probe_type_block);
1508   tcase_add_test (tc_chain, test_pad_blocking_with_probe_type_blocking);
1509   tcase_add_test (tc_chain, test_queue_src_caps_notify_linked);
1510   tcase_add_test (tc_chain, test_queue_src_caps_notify_not_linked);
1511 #if 0
1512   tcase_add_test (tc_chain, test_block_async_replace_callback);
1513 #endif
1514   tcase_add_test (tc_chain, test_block_async_full_destroy);
1515   tcase_add_test (tc_chain, test_block_async_full_destroy_dispose);
1516   tcase_add_test (tc_chain, test_block_async_replace_callback_no_flush);
1517   tcase_add_test (tc_chain, test_sticky_events);
1518
1519   return s;
1520 }
1521
1522 GST_CHECK_MAIN (gst_pad);