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