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