pad: add pending event for sticky events
[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   fail_unless (gst_pad_set_caps (src, caps) == TRUE);
131   /* can't set caps on flushing sinkpad */
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", 3);
135
136   gst_pad_set_active (sink, TRUE);
137   fail_unless (gst_pad_set_caps (sink, caps) == TRUE);
138   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
139
140   plr = gst_pad_link (src, sink);
141   fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
142   /* src caps added to pending caps on sink */
143   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
144
145   gst_pad_unlink (src, sink);
146   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
147
148   /* cleanup */
149   gst_object_unref (src);
150   gst_object_unref (sink);
151   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
152
153   gst_caps_unref (caps);
154 }
155
156 GST_END_TEST;
157
158 GST_START_TEST (test_get_allowed_caps)
159 {
160   GstPad *src, *sink;
161   GstCaps *caps, *gotcaps;
162   GstBuffer *buffer;
163   GstPadLinkReturn plr;
164
165   ASSERT_CRITICAL (gst_pad_get_allowed_caps (NULL));
166
167   buffer = gst_buffer_new ();
168   ASSERT_CRITICAL (gst_pad_get_allowed_caps ((GstPad *) buffer));
169   gst_buffer_unref (buffer);
170
171   src = gst_pad_new ("src", GST_PAD_SRC);
172   fail_if (src == NULL);
173   caps = gst_pad_get_allowed_caps (src);
174   fail_unless (caps == NULL);
175
176   caps = gst_caps_from_string ("foo/bar");
177
178   sink = gst_pad_new ("sink", GST_PAD_SINK);
179   fail_unless (gst_pad_set_caps (src, caps) == TRUE);
180   fail_if (gst_pad_set_caps (sink, caps) == TRUE);
181   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
182
183   gst_pad_set_active (sink, TRUE);
184   fail_unless (gst_pad_set_caps (sink, caps) == TRUE);
185   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
186
187   plr = gst_pad_link (src, sink);
188   fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
189
190   gotcaps = gst_pad_get_allowed_caps (src);
191   fail_if (gotcaps == NULL);
192 #if 0
193   /* FIXME, does not work, caps events are different so the sinkpad loses caps
194    * when linking */
195   fail_unless (gst_caps_is_equal (gotcaps, caps));
196 #endif
197
198   ASSERT_CAPS_REFCOUNT (gotcaps, "gotcaps", 1);
199   gst_caps_unref (gotcaps);
200
201   gst_pad_unlink (src, sink);
202
203   /* cleanup */
204   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
205   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
206   ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
207
208   gst_object_unref (src);
209   gst_object_unref (sink);
210
211   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
212   gst_caps_unref (caps);
213 }
214
215 GST_END_TEST;
216
217 static gboolean
218 name_is_valid (const gchar * name, GstPadPresence presence)
219 {
220   GstPadTemplate *new;
221   GstCaps *any = GST_CAPS_ANY;
222
223   new = gst_pad_template_new (name, GST_PAD_SRC, presence, any);
224   if (new) {
225     gst_object_unref (GST_OBJECT (new));
226     return TRUE;
227   }
228   return FALSE;
229 }
230
231 GST_START_TEST (test_name_is_valid)
232 {
233   gboolean result = FALSE;
234
235   fail_unless (name_is_valid ("src", GST_PAD_ALWAYS));
236   ASSERT_WARNING (name_is_valid ("src%", GST_PAD_ALWAYS));
237   ASSERT_WARNING (result = name_is_valid ("src%d", GST_PAD_ALWAYS));
238   fail_if (result);
239
240   fail_unless (name_is_valid ("src", GST_PAD_REQUEST));
241   ASSERT_WARNING (name_is_valid ("src%s%s", GST_PAD_REQUEST));
242   ASSERT_WARNING (name_is_valid ("src%c", GST_PAD_REQUEST));
243   ASSERT_WARNING (name_is_valid ("src%", GST_PAD_REQUEST));
244   ASSERT_WARNING (name_is_valid ("src%dsrc", GST_PAD_REQUEST));
245
246   fail_unless (name_is_valid ("src", GST_PAD_SOMETIMES));
247   fail_unless (name_is_valid ("src%c", GST_PAD_SOMETIMES));
248 }
249
250 GST_END_TEST;
251
252 static gboolean
253 _probe_handler (GstPad * pad, GstBuffer * buffer, gpointer userdata)
254 {
255   gint ret = GPOINTER_TO_INT (userdata);
256
257   if (ret == 1)
258     return TRUE;
259   return FALSE;
260 }
261
262 GST_START_TEST (test_push_unlinked)
263 {
264   GstPad *src;
265   GstCaps *caps;
266   GstBuffer *buffer;
267   gulong id;
268
269   src = gst_pad_new ("src", GST_PAD_SRC);
270   fail_if (src == NULL);
271   caps = gst_pad_get_allowed_caps (src);
272   fail_unless (caps == NULL);
273
274   caps = gst_caps_from_string ("foo/bar");
275
276   gst_pad_set_caps (src, caps);
277   ASSERT_CAPS_REFCOUNT (caps, "caps", 2);
278
279   /* pushing on an unlinked pad will drop the buffer */
280   buffer = gst_buffer_new ();
281   gst_buffer_ref (buffer);
282   fail_unless (gst_pad_push (src, buffer) == GST_FLOW_NOT_LINKED);
283   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
284   gst_buffer_unref (buffer);
285
286   /* adding a probe that returns FALSE will drop the buffer without trying
287    * to chain */
288   id = gst_pad_add_buffer_probe (src, (GCallback) _probe_handler,
289       GINT_TO_POINTER (0));
290   buffer = gst_buffer_new ();
291   gst_buffer_ref (buffer);
292   fail_unless (gst_pad_push (src, buffer) == GST_FLOW_OK);
293   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
294   gst_buffer_unref (buffer);
295   gst_pad_remove_buffer_probe (src, id);
296
297   /* adding a probe that returns TRUE will still chain the buffer,
298    * and hence drop because pad is unlinked */
299   id = gst_pad_add_buffer_probe (src, (GCallback) _probe_handler,
300       GINT_TO_POINTER (1));
301   buffer = gst_buffer_new ();
302   gst_buffer_ref (buffer);
303   fail_unless (gst_pad_push (src, buffer) == GST_FLOW_NOT_LINKED);
304   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
305   gst_buffer_unref (buffer);
306   gst_pad_remove_buffer_probe (src, id);
307
308
309   /* cleanup */
310   ASSERT_CAPS_REFCOUNT (caps, "caps", 2);
311   ASSERT_OBJECT_REFCOUNT (src, "src", 1);
312
313   gst_object_unref (src);
314
315   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
316   gst_caps_unref (caps);
317 }
318
319 GST_END_TEST;
320
321 GST_START_TEST (test_push_linked)
322 {
323   GstPad *src, *sink;
324   GstPadLinkReturn plr;
325   GstCaps *caps;
326   GstBuffer *buffer;
327   gulong id;
328
329   /* setup */
330   sink = gst_pad_new ("sink", GST_PAD_SINK);
331   fail_if (sink == NULL);
332   gst_pad_set_chain_function (sink, gst_check_chain_func);
333
334   src = gst_pad_new ("src", GST_PAD_SRC);
335   fail_if (src == NULL);
336
337   caps = gst_caps_from_string ("foo/bar");
338   /* one for me */
339   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
340
341   gst_pad_set_caps (src, caps);
342   gst_pad_set_active (sink, TRUE);
343   gst_pad_set_caps (sink, caps);
344   /* one for me and one for each set_caps */
345   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
346
347   plr = gst_pad_link (src, sink);
348   fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
349   ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
350
351   buffer = gst_buffer_new ();
352 #if 0
353   /* FIXME, new pad should be flushing */
354   gst_buffer_ref (buffer);
355   fail_unless (gst_pad_push (src, buffer) == GST_FLOW_WRONG_STATE);
356   gst_buffer_ref (buffer);
357   fail_unless (gst_pad_chain (sink, buffer) == GST_FLOW_WRONG_STATE);
358 #endif
359
360   /* activate pads */
361   gst_pad_set_active (src, TRUE);
362   gst_pad_set_active (sink, TRUE);
363
364   /* test */
365   /* pushing on a linked pad will drop the ref to the buffer */
366   gst_buffer_ref (buffer);
367   fail_unless (gst_pad_push (src, buffer) == GST_FLOW_OK);
368   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 2);
369   gst_buffer_unref (buffer);
370   fail_unless_equals_int (g_list_length (buffers), 1);
371   buffer = GST_BUFFER (buffers->data);
372   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
373   gst_buffer_unref (buffer);
374   g_list_free (buffers);
375   buffers = NULL;
376
377   /* adding a probe that returns FALSE will drop the buffer without trying
378    * to chain */
379   id = gst_pad_add_buffer_probe (src, (GCallback) _probe_handler,
380       GINT_TO_POINTER (0));
381   buffer = gst_buffer_new ();
382   gst_buffer_ref (buffer);
383   fail_unless (gst_pad_push (src, buffer) == GST_FLOW_OK);
384   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
385   gst_buffer_unref (buffer);
386   gst_pad_remove_buffer_probe (src, id);
387   fail_unless_equals_int (g_list_length (buffers), 0);
388
389   /* adding a probe that returns TRUE will still chain the buffer */
390   id = gst_pad_add_buffer_probe (src, (GCallback) _probe_handler,
391       GINT_TO_POINTER (1));
392   buffer = gst_buffer_new ();
393   gst_buffer_ref (buffer);
394   fail_unless (gst_pad_push (src, buffer) == GST_FLOW_OK);
395   gst_pad_remove_buffer_probe (src, id);
396
397   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 2);
398   gst_buffer_unref (buffer);
399   fail_unless_equals_int (g_list_length (buffers), 1);
400   buffer = GST_BUFFER (buffers->data);
401   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
402   gst_buffer_unref (buffer);
403   g_list_free (buffers);
404   buffers = NULL;
405
406   /* teardown */
407   gst_pad_unlink (src, sink);
408   ASSERT_CAPS_REFCOUNT (caps, "caps", 2);
409   gst_object_unref (src);
410   gst_object_unref (sink);
411   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
412
413   gst_caps_unref (caps);
414 }
415
416 GST_END_TEST;
417
418 static GstBuffer *
419 buffer_from_string (const gchar * str)
420 {
421   guint size;
422   GstBuffer *buf;
423   gpointer data;
424
425   size = strlen (str);
426   buf = gst_buffer_new_and_alloc (size);
427
428   data = gst_buffer_map (buf, NULL, NULL, GST_MAP_WRITE);
429   memcpy (data, str, size);
430   gst_buffer_unmap (buf, data, size);
431
432   return buf;
433 }
434
435 static gboolean
436 buffer_compare (GstBuffer * buf, const gchar * str, gsize size)
437 {
438   gboolean res;
439   gpointer data;
440
441   data = gst_buffer_map (buf, NULL, NULL, GST_MAP_READ);
442   res = memcmp (data, str, size) == 0;
443   GST_DEBUG ("%s <-> %s: %d", (gchar *) data, str, res);
444   gst_buffer_unmap (buf, data, size);
445
446   return res;
447 }
448
449 GST_START_TEST (test_push_buffer_list_compat)
450 {
451   GstPad *src, *sink;
452   GstPadLinkReturn plr;
453   GstCaps *caps;
454   GstBufferList *list;
455   GstBuffer *buffer;
456   guint len;
457
458   /* setup */
459   sink = gst_pad_new ("sink", GST_PAD_SINK);
460   fail_if (sink == NULL);
461   gst_pad_set_chain_function (sink, gst_check_chain_func);
462   /* leave chainlistfunc unset */
463
464   src = gst_pad_new ("src", GST_PAD_SRC);
465   fail_if (src == NULL);
466
467   caps = gst_caps_from_string ("foo/bar");
468
469   gst_pad_set_caps (src, caps);
470   gst_pad_set_active (sink, TRUE);
471   gst_pad_set_caps (sink, caps);
472
473   plr = gst_pad_link (src, sink);
474   fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
475
476   list = gst_buffer_list_new ();
477
478   /* activate pads */
479   gst_pad_set_active (src, TRUE);
480   gst_pad_set_active (sink, TRUE);
481
482   /* test */
483   /* adding to a buffer list will drop the ref to the buffer */
484   len = gst_buffer_list_len (list);
485
486   gst_buffer_list_add (list, buffer_from_string ("ListGroup"));
487   gst_buffer_list_add (list, buffer_from_string ("AnotherListGroup"));
488
489   fail_unless (gst_pad_push_list (src, list) == GST_FLOW_OK);
490   fail_unless_equals_int (g_list_length (buffers), 2);
491   buffer = GST_BUFFER (buffers->data);
492   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
493   fail_unless (buffer_compare (buffer, "ListGroup", 9));
494   gst_buffer_unref (buffer);
495   buffers = g_list_delete_link (buffers, buffers);
496   buffer = GST_BUFFER (buffers->data);
497   ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
498   fail_unless (buffer_compare (buffer, "AnotherListGroup", 16));
499   gst_buffer_unref (buffer);
500   buffers = g_list_delete_link (buffers, buffers);
501   fail_unless (buffers == NULL);
502
503   /* teardown */
504   gst_pad_unlink (src, sink);
505   gst_object_unref (src);
506   gst_object_unref (sink);
507   ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
508   gst_caps_unref (caps);
509 }
510
511 GST_END_TEST;
512
513 GST_START_TEST (test_flowreturn)
514 {
515   GstFlowReturn ret;
516   GQuark quark;
517
518   /* test some of the macros */
519   ret = GST_FLOW_UNEXPECTED;
520   fail_if (strcmp (gst_flow_get_name (ret), "unexpected"));
521   quark = gst_flow_to_quark (ret);
522   fail_if (strcmp (g_quark_to_string (quark), "unexpected"));
523
524   ret = GST_FLOW_RESEND;
525   fail_if (strcmp (gst_flow_get_name (ret), "resend"));
526   quark = gst_flow_to_quark (ret);
527   fail_if (strcmp (g_quark_to_string (quark), "resend"));
528
529   /* custom returns */
530   ret = GST_FLOW_CUSTOM_SUCCESS;
531   fail_if (strcmp (gst_flow_get_name (ret), "custom-success"));
532   quark = gst_flow_to_quark (ret);
533   fail_if (strcmp (g_quark_to_string (quark), "custom-success"));
534
535   ret = GST_FLOW_CUSTOM_ERROR;
536   fail_if (strcmp (gst_flow_get_name (ret), "custom-error"));
537   quark = gst_flow_to_quark (ret);
538   fail_if (strcmp (g_quark_to_string (quark), "custom-error"));
539
540   /* custom returns clamping */
541   ret = GST_FLOW_CUSTOM_SUCCESS + 2;
542   fail_if (strcmp (gst_flow_get_name (ret), "custom-success"));
543   quark = gst_flow_to_quark (ret);
544   fail_if (strcmp (g_quark_to_string (quark), "custom-success"));
545
546   ret = GST_FLOW_CUSTOM_ERROR - 2;
547   fail_if (strcmp (gst_flow_get_name (ret), "custom-error"));
548   quark = gst_flow_to_quark (ret);
549   fail_if (strcmp (g_quark_to_string (quark), "custom-error"));
550
551   /* unknown values */
552   ret = GST_FLOW_CUSTOM_ERROR + 2;
553   fail_if (strcmp (gst_flow_get_name (ret), "unknown"));
554   quark = gst_flow_to_quark (ret);
555   fail_unless (quark == 0);
556 }
557
558 GST_END_TEST;
559
560 GST_START_TEST (test_push_negotiation)
561 {
562   GstPad *src, *sink;
563   GstPadLinkReturn plr;
564   GstCaps *srccaps =
565       gst_caps_from_string ("audio/x-raw-int,width={16,32},depth={16,32}");
566   GstCaps *sinkcaps =
567       gst_caps_from_string ("audio/x-raw-int,width=32,depth={16,32}");
568   GstPadTemplate *src_template;
569   GstPadTemplate *sink_template;
570   GstCaps *caps;
571   GstBuffer *buffer;
572
573   /* setup */
574   src_template = gst_pad_template_new ("src", GST_PAD_SRC,
575       GST_PAD_ALWAYS, srccaps);
576   sink_template = gst_pad_template_new ("sink", GST_PAD_SINK,
577       GST_PAD_ALWAYS, sinkcaps);
578   gst_caps_unref (srccaps);
579   gst_caps_unref (sinkcaps);
580
581   sink = gst_pad_new_from_template (sink_template, "sink");
582   fail_if (sink == NULL);
583   gst_pad_set_chain_function (sink, gst_check_chain_func);
584
585   src = gst_pad_new_from_template (src_template, "src");
586   fail_if (src == NULL);
587
588   plr = gst_pad_link (src, sink);
589   fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
590
591   buffer = gst_buffer_new ();
592
593   /* activate pads */
594   gst_pad_set_active (src, TRUE);
595   gst_pad_set_active (sink, TRUE);
596
597   caps = gst_caps_from_string ("audio/x-raw-int,width=16,depth=16");
598
599   /* Should fail if src pad caps are incompatible with sink pad caps */
600   gst_pad_set_caps (src, caps);
601   fail_unless (gst_pad_set_caps (sink, caps) == FALSE);
602
603   /* teardown */
604   gst_pad_unlink (src, sink);
605   gst_object_unref (src);
606   gst_object_unref (sink);
607   gst_caps_unref (caps);
608   gst_object_unref (sink_template);
609   gst_object_unref (src_template);
610 }
611
612 GST_END_TEST;
613
614 /* see that an unref also unlinks the pads */
615 GST_START_TEST (test_src_unref_unlink)
616 {
617   GstPad *src, *sink;
618   GstCaps *caps;
619   GstPadLinkReturn plr;
620
621   sink = gst_pad_new ("sink", GST_PAD_SINK);
622   fail_if (sink == NULL);
623
624   src = gst_pad_new ("src", GST_PAD_SRC);
625   fail_if (src == NULL);
626
627   caps = gst_caps_from_string ("foo/bar");
628
629   gst_pad_set_caps (src, caps);
630   gst_pad_set_active (sink, TRUE);
631   gst_pad_set_caps (sink, caps);
632
633   plr = gst_pad_link (src, sink);
634   fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
635
636   /* unref the srcpad */
637   gst_object_unref (src);
638
639   /* sink should be unlinked now */
640   fail_if (gst_pad_is_linked (sink));
641
642   /* cleanup */
643   gst_object_unref (sink);
644   gst_caps_unref (caps);
645 }
646
647 GST_END_TEST;
648
649 /* see that an unref also unlinks the pads */
650 GST_START_TEST (test_sink_unref_unlink)
651 {
652   GstPad *src, *sink;
653   GstCaps *caps;
654   GstPadLinkReturn plr;
655
656   sink = gst_pad_new ("sink", GST_PAD_SINK);
657   fail_if (sink == NULL);
658
659   src = gst_pad_new ("src", GST_PAD_SRC);
660   fail_if (src == NULL);
661
662   caps = gst_caps_from_string ("foo/bar");
663
664   gst_pad_set_caps (src, caps);
665   gst_pad_set_active (sink, TRUE);
666   gst_pad_set_caps (sink, caps);
667
668   plr = gst_pad_link (src, sink);
669   fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
670
671   /* unref the sinkpad */
672   gst_object_unref (sink);
673
674   /* src should be unlinked now */
675   fail_if (gst_pad_is_linked (src));
676
677   /* cleanup */
678   gst_object_unref (src);
679   gst_caps_unref (caps);
680 }
681
682 GST_END_TEST;
683
684 static void
685 unblock_async_cb (GstPad * pad, gboolean blocked, gpointer user_data)
686 {
687   gboolean *bool_user_data = (gboolean *) user_data;
688
689   /* here we should have blocked == 1 unblocked == 0 */
690   fail_unless (bool_user_data[0] == TRUE);
691   fail_unless (bool_user_data[1] == FALSE);
692
693   bool_user_data[1] = TRUE;
694 }
695
696 static void
697 block_async_cb (GstPad * pad, gboolean blocked, gpointer user_data)
698 {
699   gboolean *bool_user_data = (gboolean *) user_data;
700
701   /* here we should have blocked == 0 unblocked == 0 */
702   fail_unless (bool_user_data[0] == FALSE);
703   fail_unless (bool_user_data[1] == FALSE);
704
705   bool_user_data[0] = blocked;
706
707   gst_pad_set_blocked_async (pad, FALSE, unblock_async_cb, user_data);
708 }
709
710 GST_START_TEST (test_block_async)
711 {
712   GstPad *pad;
713   /* we set data[0] = TRUE when the pad is blocked, data[1] = TRUE when it's
714    * unblocked */
715   gboolean data[2] = { FALSE, FALSE };
716
717   pad = gst_pad_new ("src", GST_PAD_SRC);
718   fail_unless (pad != NULL);
719
720   gst_pad_set_active (pad, TRUE);
721   gst_pad_set_blocked_async (pad, TRUE, block_async_cb, &data);
722
723   fail_unless (data[0] == FALSE);
724   fail_unless (data[1] == FALSE);
725   gst_pad_push (pad, gst_buffer_new ());
726
727   gst_object_unref (pad);
728 }
729
730 GST_END_TEST;
731
732 #if 0
733 static void
734 block_async_second (GstPad * pad, gboolean blocked, gpointer user_data)
735 {
736   gst_pad_set_blocked_async (pad, FALSE, unblock_async_cb, NULL);
737 }
738
739 static void
740 block_async_first (GstPad * pad, gboolean blocked, gpointer user_data)
741 {
742   static int n_calls = 0;
743   gboolean *bool_user_data = (gboolean *) user_data;
744
745   if (++n_calls > 1)
746     /* we expect this callback to be called only once */
747     g_warn_if_reached ();
748
749   *bool_user_data = blocked;
750
751   /* replace block_async_first with block_async_second so next time the pad is
752    * blocked the latter should be called */
753   gst_pad_set_blocked_async (pad, TRUE, block_async_second, NULL);
754
755   /* unblock temporarily, in the next push block_async_second should be called
756    */
757   gst_pad_push_event (pad, gst_event_new_flush_start ());
758 }
759
760 GST_START_TEST (test_block_async_replace_callback)
761 {
762   GstPad *pad;
763   gboolean blocked;
764
765   pad = gst_pad_new ("src", GST_PAD_SRC);
766   fail_unless (pad != NULL);
767   gst_pad_set_active (pad, TRUE);
768
769   gst_pad_set_blocked_async (pad, TRUE, block_async_first, &blocked);
770   blocked = FALSE;
771
772   gst_pad_push (pad, gst_buffer_new ());
773   fail_unless (blocked == TRUE);
774   /* block_async_first flushes to unblock */
775   gst_pad_push_event (pad, gst_event_new_flush_stop ());
776
777   /* push again, this time block_async_second should be called */
778   gst_pad_push (pad, gst_buffer_new ());
779   fail_unless (blocked == TRUE);
780
781   gst_object_unref (pad);
782 }
783
784 GST_END_TEST;
785 #endif
786
787 static void
788 block_async_full_destroy (gpointer user_data)
789 {
790   gint *state = (gint *) user_data;
791
792   fail_unless (*state < 2);
793
794   GST_DEBUG ("setting state to 2");
795   *state = 2;
796 }
797
798 static void
799 block_async_full_cb (GstPad * pad, gboolean blocked, gpointer user_data)
800 {
801   *(gint *) user_data = (gint) blocked;
802
803   gst_pad_push_event (pad, gst_event_new_flush_start ());
804   GST_DEBUG ("setting state to 1");
805 }
806
807 GST_START_TEST (test_block_async_full_destroy)
808 {
809   GstPad *pad;
810   /* 0 = unblocked, 1 = blocked, 2 = destroyed */
811   gint state = 0;
812
813   pad = gst_pad_new ("src", GST_PAD_SRC);
814   fail_unless (pad != NULL);
815   gst_pad_set_active (pad, TRUE);
816
817   gst_pad_set_blocked_async_full (pad, TRUE, block_async_full_cb,
818       &state, block_async_full_destroy);
819   fail_unless (state == 0);
820
821   gst_pad_push (pad, gst_buffer_new ());
822   /* block_async_full_cb sets state to 1 and then flushes to unblock temporarily
823    */
824   fail_unless (state == 1);
825   gst_pad_push_event (pad, gst_event_new_flush_stop ());
826
827   /* pad was already blocked so nothing happens */
828   gst_pad_set_blocked_async_full (pad, TRUE, block_async_full_cb,
829       &state, block_async_full_destroy);
830   fail_unless (state == 1);
831
832   /* unblock with the same data, callback is called */
833   gst_pad_set_blocked_async_full (pad, FALSE, block_async_full_cb,
834       &state, block_async_full_destroy);
835   fail_unless (state == 2);
836
837   /* block with the same data, callback is called */
838   state = 1;
839   gst_pad_set_blocked_async_full (pad, TRUE, block_async_full_cb,
840       &state, block_async_full_destroy);
841   fail_unless (state == 2);
842
843   /* now change user_data (to NULL in this case) so destroy_notify should be
844    * called */
845   state = 1;
846   gst_pad_set_blocked_async_full (pad, FALSE, block_async_full_cb,
847       NULL, block_async_full_destroy);
848   fail_unless (state == 2);
849
850   gst_object_unref (pad);
851 }
852
853 GST_END_TEST;
854
855 GST_START_TEST (test_block_async_full_destroy_dispose)
856 {
857   GstPad *pad;
858   /* 0 = unblocked, 1 = blocked, 2 = destroyed */
859   gint state = 0;
860
861   pad = gst_pad_new ("src", GST_PAD_SRC);
862   fail_unless (pad != NULL);
863   gst_pad_set_active (pad, TRUE);
864
865   gst_pad_set_blocked_async_full (pad, TRUE, block_async_full_cb,
866       &state, block_async_full_destroy);
867
868   gst_pad_push (pad, gst_buffer_new ());
869   /* block_async_full_cb sets state to 1 and then flushes to unblock temporarily
870    */
871   fail_unless_equals_int (state, 1);
872   gst_pad_push_event (pad, gst_event_new_flush_stop ());
873
874   /* gst_pad_dispose calls the destroy_notify function if necessary */
875   gst_object_unref (pad);
876
877   fail_unless_equals_int (state, 2);
878 }
879
880 GST_END_TEST;
881
882
883 static void
884 unblock_async_no_flush_cb (GstPad * pad, gboolean blocked, gpointer user_data)
885 {
886   gboolean *bool_user_data = (gboolean *) user_data;
887
888   /* here we should have blocked == 1 unblocked == 0 */
889
890   fail_unless (blocked == FALSE);
891
892   fail_unless (bool_user_data[0] == TRUE);
893   fail_unless (bool_user_data[1] == TRUE);
894   fail_unless (bool_user_data[2] == FALSE);
895
896   bool_user_data[2] = TRUE;
897 }
898
899
900 static void
901 unblock_async_not_called (GstPad * pad, gboolean blocked, gpointer user_data)
902 {
903   g_warn_if_reached ();
904 }
905
906 static void
907 block_async_second_no_flush (GstPad * pad, gboolean blocked, gpointer user_data)
908 {
909   gboolean *bool_user_data = (gboolean *) user_data;
910
911   fail_unless (blocked == TRUE);
912
913   fail_unless (bool_user_data[0] == TRUE);
914   fail_unless (bool_user_data[1] == FALSE);
915   fail_unless (bool_user_data[2] == FALSE);
916
917   bool_user_data[1] = TRUE;
918
919   fail_unless (gst_pad_set_blocked_async (pad, FALSE, unblock_async_no_flush_cb,
920           user_data));
921 }
922
923 static void
924 block_async_first_no_flush (GstPad * pad, gboolean blocked, gpointer user_data)
925 {
926   static int n_calls = 0;
927   gboolean *bool_user_data = (gboolean *) user_data;
928
929   fail_unless (blocked == TRUE);
930
931   if (++n_calls > 1)
932     /* we expect this callback to be called only once */
933     g_warn_if_reached ();
934
935   *bool_user_data = blocked;
936
937   fail_unless (bool_user_data[0] == TRUE);
938   fail_unless (bool_user_data[1] == FALSE);
939   fail_unless (bool_user_data[2] == FALSE);
940
941   fail_unless (gst_pad_set_blocked_async (pad, FALSE, unblock_async_not_called,
942           NULL));
943
944   /* replace block_async_first with block_async_second so next time the pad is
945    * blocked the latter should be called */
946   fail_unless (gst_pad_set_blocked_async (pad, TRUE,
947           block_async_second_no_flush, user_data));
948 }
949
950 GST_START_TEST (test_block_async_replace_callback_no_flush)
951 {
952   GstPad *pad;
953   gboolean bool_user_data[3] = { FALSE, FALSE, FALSE };
954
955   pad = gst_pad_new ("src", GST_PAD_SRC);
956   fail_unless (pad != NULL);
957   gst_pad_set_active (pad, TRUE);
958
959   fail_unless (gst_pad_set_blocked_async (pad, TRUE, block_async_first_no_flush,
960           bool_user_data));
961
962   gst_pad_push (pad, gst_buffer_new ());
963   fail_unless (bool_user_data[0] == TRUE);
964   fail_unless (bool_user_data[1] == TRUE);
965   fail_unless (bool_user_data[2] == TRUE);
966
967   gst_object_unref (pad);
968 }
969
970 GST_END_TEST;
971
972
973 static Suite *
974 gst_pad_suite (void)
975 {
976   Suite *s = suite_create ("GstPad");
977   TCase *tc_chain = tcase_create ("general");
978
979   /* turn off timeout */
980   tcase_set_timeout (tc_chain, 60);
981
982   suite_add_tcase (s, tc_chain);
983   tcase_add_test (tc_chain, test_link);
984   tcase_add_test (tc_chain, test_refcount);
985   tcase_add_test (tc_chain, test_get_allowed_caps);
986   tcase_add_test (tc_chain, test_link_unlink_threaded);
987   tcase_add_test (tc_chain, test_name_is_valid);
988   tcase_add_test (tc_chain, test_push_unlinked);
989   tcase_add_test (tc_chain, test_push_linked);
990   tcase_add_test (tc_chain, test_push_buffer_list_compat);
991   tcase_add_test (tc_chain, test_flowreturn);
992   tcase_add_test (tc_chain, test_push_negotiation);
993   tcase_add_test (tc_chain, test_src_unref_unlink);
994   tcase_add_test (tc_chain, test_sink_unref_unlink);
995   tcase_add_test (tc_chain, test_block_async);
996 #if 0
997   tcase_add_test (tc_chain, test_block_async_replace_callback);
998 #endif
999   tcase_add_test (tc_chain, test_block_async_full_destroy);
1000   tcase_add_test (tc_chain, test_block_async_full_destroy_dispose);
1001   tcase_add_test (tc_chain, test_block_async_replace_callback_no_flush);
1002
1003   return s;
1004 }
1005
1006 GST_CHECK_MAIN (gst_pad);