more leaks plumbed, added more debug-logging
[platform/upstream/gstreamer.git] / check / gst-libs / controller.c
1 /* GStreamer
2  *
3  * unit test for the controller library
4  *
5  * Copyright (C) <2005> Stefan Kost <ensonic at users dot sf dor net>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26 #include <gst/gst.h>
27 #include <gst/check/gstcheck.h>
28 #include <gst/controller/gstcontroller.h>
29
30 /* LOCAL TEST ELEMENT */
31
32 enum
33 {
34   ARG_ULONG = 1,
35   ARG_DOUBLE,
36   ARG_BOOLEAN,
37   ARG_READONLY,
38   ARG_STATIC,
39   ARG_CONSTRUCTONLY,
40   ARG_COUNT
41 };
42
43 #define GST_TYPE_TEST_MONO_SOURCE            (gst_test_mono_source_get_type ())
44 #define GST_TEST_MONO_SOURCE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TEST_MONO_SOURCE, GstTestMonoSource))
45 #define GST_TEST_MONO_SOURCE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_TEST_MONO_SOURCE, GstTestMonoSourceClass))
46 #define GST_IS_TEST_MONO_SOURCE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TEST_MONO_SOURCE))
47 #define GST_IS_TEST_MONO_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_TEST_MONO_SOURCE))
48 #define GST_TEST_MONO_SOURCE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_TEST_MONO_SOURCE, GstTestMonoSourceClass))
49
50 typedef struct _GstTestMonoSource GstTestMonoSource;
51 typedef struct _GstTestMonoSourceClass GstTestMonoSourceClass;
52
53 struct _GstTestMonoSource
54 {
55   GstElement parent;
56   gulong val_ulong;
57   gdouble val_double;
58   gboolean val_boolean;
59 };
60 struct _GstTestMonoSourceClass
61 {
62   GstElementClass parent_class;
63 };
64
65 GType gst_test_mono_source_get_type (void);
66
67 static void
68 gst_test_mono_source_get_property (GObject * object,
69     guint property_id, GValue * value, GParamSpec * pspec)
70 {
71   GstTestMonoSource *self = GST_TEST_MONO_SOURCE (object);
72
73   switch (property_id) {
74     case ARG_ULONG:
75       g_value_set_ulong (value, self->val_ulong);
76       break;
77     case ARG_DOUBLE:
78       g_value_set_double (value, self->val_double);
79       break;
80     case ARG_BOOLEAN:
81       g_value_set_boolean (value, self->val_boolean);
82       break;
83     default:
84       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
85       break;
86   }
87 }
88
89 static void
90 gst_test_mono_source_set_property (GObject * object,
91     guint property_id, const GValue * value, GParamSpec * pspec)
92 {
93   GstTestMonoSource *self = GST_TEST_MONO_SOURCE (object);
94
95   switch (property_id) {
96     case ARG_ULONG:
97       self->val_ulong = g_value_get_ulong (value);
98       break;
99     case ARG_DOUBLE:
100       self->val_double = g_value_get_double (value);
101       break;
102     case ARG_BOOLEAN:
103       self->val_boolean = g_value_get_boolean (value);
104       break;
105     case ARG_CONSTRUCTONLY:
106       break;
107     default:
108       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
109       break;
110   }
111 }
112
113 static void
114 gst_test_mono_source_class_init (GstTestMonoSourceClass * klass)
115 {
116   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
117
118   gobject_class->set_property = gst_test_mono_source_set_property;
119   gobject_class->get_property = gst_test_mono_source_get_property;
120
121   g_object_class_install_property (gobject_class, ARG_ULONG,
122       g_param_spec_ulong ("ulong",
123           "ulong prop",
124           "ulong number parameter for the test_mono_source",
125           0, G_MAXULONG, 0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
126
127   g_object_class_install_property (gobject_class, ARG_DOUBLE,
128       g_param_spec_double ("double",
129           "double prop",
130           "double number parameter for the test_mono_source",
131           0.0, 100.0, 0.0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
132
133   g_object_class_install_property (gobject_class, ARG_BOOLEAN,
134       g_param_spec_boolean ("boolean",
135           "boolean prop",
136           "boolean parameter for the test_mono_source",
137           FALSE, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
138
139   g_object_class_install_property (gobject_class, ARG_READONLY,
140       g_param_spec_ulong ("readonly",
141           "readonly prop",
142           "readonly parameter for the test_mono_source",
143           0, G_MAXULONG, 0, G_PARAM_READABLE | GST_PARAM_CONTROLLABLE));
144
145   g_object_class_install_property (gobject_class, ARG_STATIC,
146       g_param_spec_ulong ("static",
147           "static prop",
148           "static parameter for the test_mono_source",
149           0, G_MAXULONG, 0, G_PARAM_READWRITE));
150
151   g_object_class_install_property (gobject_class, ARG_CONSTRUCTONLY,
152       g_param_spec_ulong ("construct-only",
153           "construct-only prop",
154           "construct-only parameter for the test_mono_source",
155           0, G_MAXULONG, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
156 }
157
158 static void
159 gst_test_mono_source_base_init (GstTestMonoSourceClass * klass)
160 {
161   static const GstElementDetails details = {
162     "Monophonic source for unit tests",
163     "Source/Audio/MonoSource",
164     "Use in unit tests",
165     "Stefan Kost <ensonic@users.sf.net>"
166   };
167   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
168
169   gst_element_class_set_details (element_class, &details);
170 }
171
172 GType
173 gst_test_mono_source_get_type (void)
174 {
175   static GType type = 0;
176
177   if (type == 0) {
178     static const GTypeInfo info = {
179       (guint16) sizeof (GstTestMonoSourceClass),
180       (GBaseInitFunc) gst_test_mono_source_base_init,   // base_init
181       NULL,                     // base_finalize
182       (GClassInitFunc) gst_test_mono_source_class_init, // class_init
183       NULL,                     // class_finalize
184       NULL,                     // class_data
185       (guint16) sizeof (GstTestMonoSource),
186       0,                        // n_preallocs
187       NULL,                     // instance_init
188       NULL                      // value_table
189     };
190     type =
191         g_type_register_static (GST_TYPE_ELEMENT, "GstTestMonoSource", &info,
192         0);
193   }
194   return type;
195 }
196
197 static gboolean
198 plugin_init (GstPlugin * plugin)
199 {
200   gboolean res = TRUE;
201
202   res &= gst_element_register (plugin, "testmonosource", GST_RANK_NONE,
203       GST_TYPE_TEST_MONO_SOURCE);
204   return res;
205 }
206
207 GST_PLUGIN_DEFINE_STATIC (GST_VERSION_MAJOR,
208     GST_VERSION_MINOR,
209     "gst-test",
210     "controller test plugin - several unit test support elements",
211     plugin_init, VERSION, GST_LICENSE, GST_PACKAGE, GST_ORIGIN);
212
213 /*
214 static void __attribute__ ((constructor))
215 _gst_plugin_static_init__plugin_init (void)
216 {
217   static GstPluginDesc plugin_desc_ = {
218     GST_VERSION_MAJOR,
219     GST_VERSION_MINOR,
220     "gst-test",
221     "controller test plugin - several unit test support elements",
222     plugin_init,
223     VERSION,
224     GST_LICENSE,
225     PACKAGE,
226     GST_PACKAGE,
227     GST_ORIGIN,
228     GST_PADDING_INIT
229   };
230   _gst_plugin_register_static (&plugin_desc_);
231 }
232 */
233 /* TESTS */
234 /* double init should not harm */
235 GST_START_TEST (controller_init)
236 {
237   gst_controller_init (NULL, NULL);
238 }
239
240 GST_END_TEST;
241
242 /* tests for an element with no controlled params */
243 GST_START_TEST (controller_new_fail1)
244 {
245   GstController *ctrl;
246   GstElement *elem;
247
248   elem = gst_element_factory_make ("fakesrc", "test_source");
249
250   /* that property should not exist */
251   ctrl = gst_controller_new (G_OBJECT (elem), "_schrompf_", NULL);
252   fail_unless (ctrl == NULL, NULL);
253
254   gst_object_unref (elem);
255 }
256
257 GST_END_TEST;
258
259 /* tests for an element with controlled params, but none given */
260 GST_START_TEST (controller_new_fail2)
261 {
262   GstController *ctrl;
263   GstElement *elem;
264
265   elem = gst_element_factory_make ("testmonosource", "test_source");
266
267   /* no property given */
268   ctrl = gst_controller_new (G_OBJECT (elem), NULL);
269   fail_unless (ctrl == NULL, NULL);
270
271   gst_object_unref (elem);
272 }
273
274 GST_END_TEST;
275
276 /* tests for readonly params */
277 GST_START_TEST (controller_new_fail3)
278 {
279   GstController *ctrl;
280   GstElement *elem;
281
282   elem = gst_element_factory_make ("testmonosource", "test_source");
283
284   /* that property should exist and but is readonly */
285   ASSERT_CRITICAL (ctrl =
286       gst_controller_new (G_OBJECT (elem), "readonly", NULL));
287   fail_unless (ctrl == NULL, NULL);
288
289   gst_object_unref (elem);
290 }
291
292 GST_END_TEST;
293
294 /* tests for static params */
295 GST_START_TEST (controller_new_fail4)
296 {
297   GstController *ctrl;
298   GstElement *elem;
299
300   elem = gst_element_factory_make ("testmonosource", "test_source");
301
302   /* that property should exist and but is not controlable */
303   ASSERT_CRITICAL (ctrl = gst_controller_new (G_OBJECT (elem), "static", NULL));
304   fail_unless (ctrl == NULL, NULL);
305
306   gst_object_unref (elem);
307 }
308
309 GST_END_TEST;
310
311 /* tests for static params */
312 GST_START_TEST (controller_new_fail5)
313 {
314   GstController *ctrl;
315   GstElement *elem;
316
317   elem = gst_element_factory_make ("testmonosource", "test_source");
318
319   /* that property should exist and but is construct-only */
320   ASSERT_CRITICAL (ctrl =
321       gst_controller_new (G_OBJECT (elem), "construct-only", NULL));
322   fail_unless (ctrl == NULL, NULL);
323
324   gst_object_unref (elem);
325 }
326
327 GST_END_TEST;
328
329
330 /* tests for an element with controlled params */
331 GST_START_TEST (controller_new_okay1)
332 {
333   GstController *ctrl;
334   GstElement *elem;
335
336   elem = gst_element_factory_make ("testmonosource", "test_source");
337
338   /* that property should exist and should be controllable */
339   ctrl = gst_controller_new (G_OBJECT (elem), "ulong", NULL);
340   fail_unless (ctrl != NULL, NULL);
341
342   GST_INFO ("controller->ref_count=%d", G_OBJECT (ctrl)->ref_count);
343   g_object_unref (ctrl);
344   gst_object_unref (elem);
345 }
346
347 GST_END_TEST;
348
349 /* tests for an element with several controlled params */
350 GST_START_TEST (controller_new_okay2)
351 {
352   GstController *ctrl;
353   GstElement *elem;
354
355   elem = gst_element_factory_make ("testmonosource", "test_source");
356
357   /* that property should exist and should be controllable */
358   ctrl = gst_controller_new (G_OBJECT (elem), "ulong", "double", NULL);
359   fail_unless (ctrl != NULL, NULL);
360
361   GST_INFO ("controller->ref_count=%d", G_OBJECT (ctrl)->ref_count);
362   g_object_unref (ctrl);
363   gst_object_unref (elem);
364 }
365
366 GST_END_TEST;
367
368 /* controlling several params should return the same controller */
369 GST_START_TEST (controller_new_okay3)
370 {
371   GstController *ctrl1, *ctrl2;
372   GstElement *elem;
373
374   elem = gst_element_factory_make ("testmonosource", "test_source");
375
376   /* that property should exist and should be controllable */
377   ctrl1 = gst_controller_new (G_OBJECT (elem), "ulong", NULL);
378   fail_unless (ctrl1 != NULL, NULL);
379
380   /* that property should exist and should be controllable */
381   ctrl2 = gst_controller_new (G_OBJECT (elem), "double", NULL);
382   fail_unless (ctrl2 != NULL, NULL);
383   fail_unless (ctrl1 == ctrl2, NULL);
384
385   GST_INFO ("controller->ref_count=%d", G_OBJECT (ctrl1)->ref_count);
386   g_object_unref (ctrl1);
387   gst_object_unref (elem);
388 }
389
390 GST_END_TEST;
391
392 /* controlling a params twice should be handled */
393 GST_START_TEST (controller_param_twice)
394 {
395   GstController *ctrl;
396   GstElement *elem;
397   gboolean res;
398
399   elem = gst_element_factory_make ("testmonosource", "test_source");
400
401   /* that property should exist and should be controllable */
402   ctrl = gst_controller_new (G_OBJECT (elem), "ulong", "ulong", NULL);
403   fail_unless (ctrl != NULL, NULL);
404
405   /* it should have been added at least once, let remove it */
406   res = gst_controller_remove_properties (ctrl, "ulong", NULL);
407   fail_unless (res, NULL);
408
409   /* removing it agian should not work */
410   res = gst_controller_remove_properties (ctrl, "ulong", NULL);
411   fail_unless (!res, NULL);
412
413   GST_INFO ("controller->ref_count=%d", G_OBJECT (ctrl)->ref_count);
414   g_object_unref (ctrl);
415   gst_object_unref (elem);
416 }
417
418 GST_END_TEST;
419
420 /* tests if we cleanup properly */
421 GST_START_TEST (controller_finalize)
422 {
423   GstController *ctrl;
424   GstElement *elem;
425
426   elem = gst_element_factory_make ("testmonosource", "test_source");
427
428   /* that property should exist and should be controllable */
429   ctrl = gst_controller_new (G_OBJECT (elem), "ulong", NULL);
430   fail_unless (ctrl != NULL, NULL);
431
432   /* free the controller */
433   g_object_unref (ctrl);
434
435   /* object shouldn't have a controller anymore */
436   ctrl = gst_object_get_controller (G_OBJECT (elem));
437   fail_unless (ctrl == NULL, NULL);
438
439   gst_object_unref (elem);
440 }
441
442 GST_END_TEST;
443
444 /* test timed value handling without interpolation */
445 GST_START_TEST (controller_interpolate_none)
446 {
447   GstController *ctrl;
448   GstElement *elem;
449   gboolean res;
450   GValue val_ulong = { 0, };
451
452   elem = gst_element_factory_make ("testmonosource", "test_source");
453
454   /* that property should exist and should be controllable */
455   ctrl = gst_controller_new (G_OBJECT (elem), "ulong", NULL);
456   fail_unless (ctrl != NULL, NULL);
457
458   /* set interpolation mode */
459   gst_controller_set_interpolation_mode (ctrl, "ulong", GST_INTERPOLATE_NONE);
460
461   /* set control values */
462   g_value_init (&val_ulong, G_TYPE_ULONG);
463   g_value_set_ulong (&val_ulong, 0);
464   res = gst_controller_set (ctrl, "ulong", 0 * GST_SECOND, &val_ulong);
465   fail_unless (res, NULL);
466   g_value_set_ulong (&val_ulong, 100);
467   res = gst_controller_set (ctrl, "ulong", 2 * GST_SECOND, &val_ulong);
468   fail_unless (res, NULL);
469
470   /* now pull in values for some timestamps */
471   gst_controller_sink_values (ctrl, 0 * GST_SECOND);
472   fail_unless (GST_TEST_MONO_SOURCE (elem)->val_ulong == 0, NULL);
473   gst_controller_sink_values (ctrl, 1 * GST_SECOND);
474   fail_unless (GST_TEST_MONO_SOURCE (elem)->val_ulong == 0, NULL);
475   gst_controller_sink_values (ctrl, 2 * GST_SECOND);
476   fail_unless (GST_TEST_MONO_SOURCE (elem)->val_ulong == 100, NULL);
477
478   GST_INFO ("controller->ref_count=%d", G_OBJECT (ctrl)->ref_count);
479   g_object_unref (ctrl);
480   gst_object_unref (elem);
481 }
482
483 GST_END_TEST;
484
485 /* tests if we can run helper methods against any GObject */
486 GST_START_TEST (controller_helper_any_gobject)
487 {
488   GstElement *elem;
489   gboolean res;
490
491   elem = gst_element_factory_make ("bin", "test_elem");
492
493   /* that element is not controllable */
494   res = gst_object_sink_values (G_OBJECT (elem), 0LL);
495   fail_unless (res == FALSE, NULL);
496
497   gst_object_unref (elem);
498 }
499
500 GST_END_TEST;
501
502
503 Suite *
504 gst_controller_suite (void)
505 {
506   Suite *s = suite_create ("Controller");
507   TCase *tc = tcase_create ("general");
508
509   suite_add_tcase (s, tc);
510   tcase_add_test (tc, controller_init);
511   tcase_add_test (tc, controller_new_fail1);
512   tcase_add_test (tc, controller_new_fail2);
513   tcase_add_test (tc, controller_new_fail3);
514   tcase_add_test (tc, controller_new_fail4);
515   tcase_add_test (tc, controller_new_fail5);
516   tcase_add_test (tc, controller_new_okay1);
517   tcase_add_test (tc, controller_new_okay2);
518   tcase_add_test (tc, controller_new_okay3);
519   tcase_add_test (tc, controller_param_twice);
520   tcase_add_test (tc, controller_finalize);
521   tcase_add_test (tc, controller_interpolate_none);
522   tcase_add_test (tc, controller_helper_any_gobject);
523
524   return s;
525 }
526
527 int
528 main (int argc, char **argv)
529 {
530   int nf;
531
532   Suite *s = gst_controller_suite ();
533   SRunner *sr = srunner_create (s);
534
535   gst_check_init (&argc, &argv);
536   gst_controller_init (NULL, NULL);
537
538   srunner_run_all (sr, CK_NORMAL);
539   nf = srunner_ntests_failed (sr);
540   srunner_free (sr);
541
542   return nf;
543 }