*.c: Don't cast to GST_OBJECT when reffing or unreffing. Large source-munging commit!!!
[platform/upstream/gstreamer.git] / check / gst / gstghostpad.c
1 /* GStreamer
2  * Copyright (C) 2005 Wim Taymans <wim@fluendo.com>
3  *
4  * gstghostpad.c: Unit test for GstGhostPad
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 "../gstcheck.h"
23
24 static void
25 assert_gstrefcount (gpointer p, gint i)
26 {
27   if (GST_OBJECT_REFCOUNT_VALUE (p) != i)
28     g_critical ("Expected refcount %d for %s, got %d", i, GST_OBJECT_NAME (p),
29         GST_OBJECT_REFCOUNT_VALUE (p));
30 }
31
32 START_TEST (test_ghost_pads)
33 {
34   GstElement *b1, *b2, *src, *i1, *sink;
35   GstPad *gsink, *gsrc, *gisrc, *gisink, *isink, *isrc, *fsrc, *fsink;
36
37   b1 = gst_element_factory_make ("pipeline", NULL);
38   b2 = gst_element_factory_make ("bin", NULL);
39   src = gst_element_factory_make ("fakesrc", NULL);
40   g_object_set (src, "num-buffers", (int) 10, NULL);
41   i1 = gst_element_factory_make ("identity", NULL);
42   sink = gst_element_factory_make ("fakesink", NULL);
43
44   fail_unless (gst_bin_add (GST_BIN (b2), i1));
45   fail_unless (gst_bin_add (GST_BIN (b1), src));
46   fail_unless (gst_bin_add (GST_BIN (b1), b2));
47   fail_unless (gst_bin_add (GST_BIN (b1), sink));
48   fail_unless (gst_element_link_pads (src, NULL, i1, NULL));
49   fail_unless (gst_element_link_pads (i1, NULL, sink, NULL));
50   GST_LOCK (b2);
51   fail_unless (b2->numsinkpads == 1);
52   fail_unless (GST_IS_GHOST_PAD (b2->sinkpads->data));
53   fail_unless (b2->numsrcpads == 1);
54   fail_unless (GST_IS_GHOST_PAD (b2->srcpads->data));
55   GST_UNLOCK (b2);
56
57   fsrc = gst_element_get_pad (src, "src");
58   fail_unless (fsrc != NULL);
59   gsink = GST_PAD (gst_object_ref (b2->sinkpads->data));
60   fail_unless (gsink != NULL);
61   gsrc = GST_PAD (gst_object_ref (b2->srcpads->data));
62   fail_unless (gsrc != NULL);
63   fsink = gst_element_get_pad (sink, "sink");
64   fail_unless (fsink != NULL);
65
66   isink = gst_element_get_pad (i1, "sink");
67   fail_unless (isink != NULL);
68   isrc = gst_element_get_pad (i1, "src");
69   fail_unless (isrc != NULL);
70   gisrc = gst_pad_get_peer (isink);
71   fail_unless (gisrc != NULL);
72   gisink = gst_pad_get_peer (isrc);
73   fail_unless (gisink != NULL);
74
75   /* all objects above have one refcount owned by us as well */
76
77   assert_gstrefcount (fsrc, 3); /* parent and gisrc */
78   assert_gstrefcount (gsink, 2);        /* parent */
79   assert_gstrefcount (gsrc, 2); /* parent */
80   assert_gstrefcount (fsink, 3);        /* parent and gisink */
81
82   assert_gstrefcount (gisrc, 2);        /* parent */
83   assert_gstrefcount (isink, 3);        /* parent and gsink */
84   assert_gstrefcount (gisink, 2);       /* parent */
85   assert_gstrefcount (isrc, 3); /* parent and gsrc */
86
87   fail_unless (gst_element_set_state (b1,
88           GST_STATE_PLAYING) == GST_STATE_SUCCESS);
89
90   fail_unless (gst_element_set_state (b1, GST_STATE_NULL) == GST_STATE_SUCCESS);
91
92   gst_object_unref (b1);
93   /* unreffing the bin will unref all elements, which will unlink and unparent
94    * all pads */
95
96   /* FIXME: ghost pads need to drop their internal pad in the unlink function,
97    * but can't right now. So internal pads have a ref from their parent, and the
98    * internal pads' targets have refs from the internals. When we do the last
99    * unref on the ghost pads, these refs should go away.
100    */
101
102   assert_gstrefcount (fsrc, 2); /* gisrc */
103   assert_gstrefcount (gsink, 1);
104   assert_gstrefcount (gsrc, 1);
105   assert_gstrefcount (fsink, 2);        /* gisink */
106
107   assert_gstrefcount (gisrc, 2);        /* gsink -- fixme drop ref in unlink */
108   assert_gstrefcount (isink, 2);        /* gsink */
109   assert_gstrefcount (gisink, 2);       /* gsrc -- fixme drop ref in unlink */
110   assert_gstrefcount (isrc, 2); /* gsrc */
111
112   /* while the fixme isn't fixed, check cleanup */
113   gst_object_unref (gsink);
114   assert_gstrefcount (isink, 1);
115   assert_gstrefcount (gisrc, 1);
116   assert_gstrefcount (fsrc, 2); /* gisrc */
117   gst_object_unref (gisrc);
118   assert_gstrefcount (fsrc, 1);
119
120   gst_object_unref (gsrc);
121   assert_gstrefcount (isrc, 1);
122   assert_gstrefcount (gisink, 1);
123   assert_gstrefcount (fsink, 2);        /* gisrc */
124   gst_object_unref (gisink);
125   assert_gstrefcount (fsink, 1);
126 }
127 END_TEST Suite *
128 gst_ghost_pad_suite (void)
129 {
130   Suite *s = suite_create ("GstGhostPad");
131   TCase *tc_chain = tcase_create ("ghost pad tests");
132
133   suite_add_tcase (s, tc_chain);
134   tcase_add_test (tc_chain, test_ghost_pads);
135
136   return s;
137 }
138
139 int
140 main (int argc, char **argv)
141 {
142   int nf;
143
144   Suite *s = gst_ghost_pad_suite ();
145   SRunner *sr = srunner_create (s);
146
147   gst_check_init (&argc, &argv);
148
149   srunner_run_all (sr, CK_NORMAL);
150   nf = srunner_ntests_failed (sr);
151   srunner_free (sr);
152
153   return nf;
154 }