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