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