Use g_memdup2() where available and add fallback for older GLib versions
[platform/upstream/gstreamer.git] / tests / check / gst / gstinfo.c
1 /* GStreamer
2  *
3  * Unit tests for GstInfo
4  *
5  * Copyright (C) 2006 Tim-Philipp Müller <tim centricular 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., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include <gst/check/gstcheck.h>
27
28 #include <string.h>
29
30 #ifndef GST_DISABLE_GST_DEBUG
31
32 static GList *messages;         /* NULL */
33 static gboolean save_messages;  /* FALSE */
34
35 static void
36 printf_extension_log_func (GstDebugCategory * category,
37     GstDebugLevel level, const gchar * file, const gchar * function,
38     gint line, GObject * object, GstDebugMessage * message, gpointer unused)
39 {
40   const gchar *dbg_msg;
41
42   dbg_msg = gst_debug_message_get (message);
43   fail_unless (dbg_msg != NULL);
44
45   if (save_messages && g_str_equal (category->name, "check"))
46     messages = g_list_append (messages, g_strdup (dbg_msg));
47
48   /* g_print ("%s\n", dbg_msg); */
49
50   /* quick hack to still get stuff to show if GST_DEBUG is set */
51   if (g_getenv ("GST_DEBUG")) {
52     gst_debug_log_default (category, level, file, function, line, object,
53         message, unused);
54   }
55 }
56
57 /* check our GST_PTR_FORMAT printf extension stuff */
58 GST_START_TEST (info_ptr_format_printf_extension)
59 {
60   /* set up our own log function to make sure the code in gstinfo is actually
61    * executed without GST_DEBUG being set or it being output to stdout */
62   gst_debug_remove_log_function (gst_debug_log_default);
63   gst_debug_add_log_function (printf_extension_log_func, NULL, NULL);
64
65   gst_debug_set_default_threshold (GST_LEVEL_LOG);
66
67   /* NULL object */
68   GST_LOG ("NULL: %" GST_PTR_FORMAT, (gpointer) NULL);
69
70   /* structure */
71   {
72     GstStructure *s;
73
74     s = gst_structure_new ("foo/bar", "number", G_TYPE_INT, 1,
75         "string", G_TYPE_STRING, "s", "float-number", G_TYPE_DOUBLE,
76         (gdouble) 424242.42, NULL);
77
78     GST_LOG ("STRUCTURE: %" GST_PTR_FORMAT, s);
79     gst_structure_free (s);
80   }
81
82   /* message */
83   {
84     GstMessage *msg;
85
86     msg = gst_message_new_element (NULL,
87         gst_structure_new ("redirect", "new-location", G_TYPE_STRING,
88             "http://foobar.com/r0x0r.ogg", "minimum-bitrate", G_TYPE_INT,
89             56000, NULL));
90
91     GST_LOG ("MESSAGE: %" GST_PTR_FORMAT, msg);
92     gst_message_unref (msg);
93   }
94
95   /* buffer and buffer list */
96   {
97     GstBufferList *list;
98     GstBuffer *buf;
99
100     buf = gst_buffer_new_allocate (NULL, 42, NULL);
101     GST_BUFFER_PTS (buf) = 5 * GST_SECOND;
102     GST_BUFFER_DURATION (buf) = GST_SECOND;
103     GST_LOG ("BUFFER: %" GST_PTR_FORMAT, buf);
104
105     list = gst_buffer_list_new ();
106     gst_buffer_list_add (list, buf);
107     buf = gst_buffer_new_allocate (NULL, 58, NULL);
108     gst_buffer_list_add (list, buf);
109     GST_LOG ("BUFFERLIST: %" GST_PTR_FORMAT, list);
110     gst_buffer_list_unref (list);
111   }
112
113 #if 0
114   /* TODO: GObject */
115   {
116     GST_LOG ("GOBJECT: %" GST_PTR_FORMAT, obj);
117   }
118
119   /* TODO: GstObject */
120   {
121     GST_LOG ("GSTOBJECT: %" GST_PTR_FORMAT, obj);
122   }
123
124   /* TODO: GstPad */
125   {
126     GST_LOG ("PAD: %" GST_PTR_FORMAT, pad);
127   }
128
129   /* TODO: GstCaps */
130   {
131     GST_LOG ("PAD: %" GST_PTR_FORMAT, pad);
132   }
133 #endif
134
135   /* clean up */
136   gst_debug_set_default_threshold (GST_LEVEL_NONE);
137   gst_debug_add_log_function (gst_debug_log_default, NULL, NULL);
138   gst_debug_remove_log_function (printf_extension_log_func);
139 }
140
141 GST_END_TEST;
142
143 /* check our GST_SEGMENT_FORMAT printf extension stuff */
144 GST_START_TEST (info_segment_format_printf_extension)
145 {
146   /* set up our own log function to make sure the code in gstinfo is actually
147    * executed without GST_DEBUG being set or it being output to stdout */
148   gst_debug_remove_log_function (gst_debug_log_default);
149   gst_debug_add_log_function (printf_extension_log_func, NULL, NULL);
150
151   gst_debug_set_default_threshold (GST_LEVEL_LOG);
152
153   /* TIME segment */
154   {
155     GstSegment segment;
156
157     gst_segment_init (&segment, GST_FORMAT_TIME);
158
159     segment.rate = 1.0;
160     segment.applied_rate = 2.0;
161     segment.start = 0;
162     segment.stop = 5 * 60 * GST_SECOND;
163     segment.time = 0;
164
165     segment.position = 2 * GST_SECOND;
166     segment.duration = 90 * 60 * GST_SECOND;
167
168     GST_LOG ("TIME: %" GST_SEGMENT_FORMAT, &segment);
169   }
170
171   /* BYTE segment */
172   {
173     GstSegment segment;
174
175     gst_segment_init (&segment, GST_FORMAT_BYTES);
176
177     segment.rate = 1.0;
178     segment.applied_rate = 1.0;
179     segment.start = 0;
180     segment.stop = 9999999;
181     segment.time = 0;
182
183     GST_LOG ("BYTE: %" GST_SEGMENT_FORMAT, &segment);
184   }
185
186   /* UNKNOWN format segment (format numbers are consecutive from 0) */
187   {
188     GstSegment segment;
189
190     gst_segment_init (&segment, 98765432);
191
192     segment.rate = 1.0;
193     segment.applied_rate = 1.0;
194     segment.start = 0;
195     segment.stop = 987654321;
196     segment.time = 0;
197
198     GST_LOG ("UNKNOWN: %" GST_SEGMENT_FORMAT, &segment);
199   }
200
201   /* UNDEFINED format segment */
202   {
203     GstSegment segment;
204
205     gst_segment_init (&segment, GST_FORMAT_UNDEFINED);
206
207     GST_LOG ("UNDEFINED: %" GST_SEGMENT_FORMAT, &segment);
208   }
209
210   /* NULL segment */
211   GST_LOG ("NULL: %" GST_SEGMENT_FORMAT, (GstSegment *) NULL);
212
213   /* clean up */
214   gst_debug_set_default_threshold (GST_LEVEL_NONE);
215   gst_debug_add_log_function (gst_debug_log_default, NULL, NULL);
216   gst_debug_remove_log_function (printf_extension_log_func);
217 }
218
219 GST_END_TEST;
220
221 GST_START_TEST (info_log_handler)
222 {
223   guint removed;
224
225   removed = gst_debug_remove_log_function (gst_debug_log_default);
226   fail_unless_equals_int (removed, 1);
227 }
228
229 GST_END_TEST;
230
231 GST_START_TEST (info_dump_mem)
232 {
233   GstDebugCategory *cat = NULL;
234   GstElement *e;
235
236   const guint8 data[] = { 0x00, 0x00, 0x00, 0x20, 0x66, 0x74, 0x79, 0x70,
237     0x71, 0x74, 0x20, 0x20, 0x20, 0x05, 0x03, 0x00, 0x71, 0x74, 0x20, 0x20,
238     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
239     0x00, 0x00, 0xef, 0xe1, 0x6d, 0x6f, 0x6f, 0x76, 0x00, 0x00, 0x00, 0x6c,
240     0x6d, 0x76, 0x68, 0x64, 0x00, 0x00, 0x00, 0x00, 0xbf, 0xd1, 0x00, 0x1d,
241     0xbf, 0xd1, 0x00, 0x1e, 0x00, 0x00, 0x0b, 0xb5, 0x00, 0x04, 0x59, 0xc5,
242     0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
243     0x00, 0x00, 0x00, 0x00, 0x00, 0x01, '%', 's', '%', 's'
244   };
245
246   e = gst_pipeline_new ("pipeline");
247   GST_DEBUG_CATEGORY_INIT (cat, "dumpcat", 0, "data dump debug category");
248   GST_MEMDUMP ("quicktime header", data, sizeof (data));
249   GST_MEMDUMP (NULL, data, sizeof (data));
250   GST_CAT_MEMDUMP (cat, "quicktime header", data, sizeof (data));
251   GST_MEMDUMP_OBJECT (e, "object stuff", data, sizeof (data));
252   GST_CAT_MEMDUMP_OBJECT (cat, e, "object/cat stuff", data, sizeof (data));
253   gst_object_unref (e);
254 }
255
256 GST_END_TEST;
257
258 GST_START_TEST (info_fixme)
259 {
260   GstDebugCategory *cat = NULL;
261   GstElement *e;
262
263   e = gst_pipeline_new ("pipeline");
264   GST_DEBUG_CATEGORY_INIT (cat, "fixcat", 0, "FIXME debug category");
265   GST_FIXME ("fix %s thing", "this");
266   GST_FIXME_OBJECT (e, "fix %s object", "this");
267   GST_CAT_FIXME (cat, "fix some%s in this category", "thing");
268   GST_CAT_FIXME_OBJECT (cat, e, "fix some%s in this cat and object", "thing");
269   gst_object_unref (e);
270 }
271
272 GST_END_TEST;
273
274 /* need this indirection so the compiler doesn't check the printf format
275  * like it would if we used GST_INFO directly (it would complain) */
276 static void
277 call_GST_INFO (const gchar * format, ...)
278 {
279   va_list var_args;
280
281   va_start (var_args, format);
282   gst_debug_log_valist (GST_CAT_DEFAULT, GST_LEVEL_INFO, __FILE__, GST_FUNCTION,
283       __LINE__, NULL, format, var_args);
284   va_end (var_args);
285 }
286
287 GST_START_TEST (info_old_printf_extensions)
288 {
289   GstSegment segment;
290   GstCaps *caps;
291   gchar *str;
292
293   /* set up our own log function to make sure the code in gstinfo is actually
294    * executed without GST_DEBUG being set or it being output to stdout */
295   gst_debug_remove_log_function (gst_debug_log_default);
296   gst_debug_add_log_function (printf_extension_log_func, NULL, NULL);
297
298   gst_debug_set_default_threshold (GST_LEVEL_LOG);
299
300   save_messages = TRUE;
301
302   fail_unless (messages == NULL);
303
304   gst_segment_init (&segment, GST_FORMAT_TIME);
305   caps = gst_caps_new_simple ("foo/bar", "width", G_TYPE_INT, 4096,
306       "framerate", GST_TYPE_FRACTION, 50, 1, "format", G_TYPE_STRING, "ARGB",
307       NULL);
308   call_GST_INFO ("Segment %Q, caps are %P", &segment, caps);
309   gst_caps_unref (caps);
310
311   fail_unless_equals_int (g_list_length (messages), 1);
312   str = (gchar *) messages->data;
313   fail_unless (str != NULL);
314
315   GST_INFO ("str = '%s'", str);
316
317   fail_unless (strstr (str, "time") != NULL);
318   fail_unless (strstr (str, "start=0:00:00.000000000") != NULL);
319   fail_unless (strstr (str, "stop=99:99:99.999999999") != NULL);
320   fail_unless (strstr (str, "applied_rate=1.000000") != NULL);
321
322   fail_unless (strstr (str, " caps are ") != NULL);
323   fail_unless (strstr (str, "foo/bar") != NULL);
324   fail_unless (strstr (str, "width=(int)4096") != NULL);
325   fail_unless (strstr (str, "framerate=(fraction)50/1") != NULL);
326   fail_unless (strstr (str, "ARGB") != NULL);
327
328   /* clean up */
329   gst_debug_set_default_threshold (GST_LEVEL_NONE);
330   gst_debug_add_log_function (gst_debug_log_default, NULL, NULL);
331   gst_debug_remove_log_function (printf_extension_log_func);
332   save_messages = FALSE;
333   g_list_free_full (messages, (GDestroyNotify) g_free);
334   messages = NULL;
335 }
336
337 GST_END_TEST;
338
339 GST_START_TEST (info_register_same_debug_category_twice)
340 {
341   GstDebugCategory *cat1 = NULL, *cat2 = NULL;
342
343   GST_DEBUG_CATEGORY_INIT (cat1, "dupli-cat", 0, "Going once");
344   GST_DEBUG_CATEGORY_INIT (cat2, "dupli-cat", 0, "Going twice");
345
346   fail_unless_equals_pointer (cat1, cat2);
347
348   fail_unless_equals_string (gst_debug_category_get_name (cat1), "dupli-cat");
349   fail_unless_equals_string (gst_debug_category_get_description (cat1),
350       "Going once");
351 }
352
353 GST_END_TEST;
354
355 GST_START_TEST (info_set_and_unset_single)
356 {
357   GstDebugLevel orig = gst_debug_get_default_threshold ();
358   GstDebugLevel cat1, cat2;
359   GstDebugCategory *states;
360
361   GST_DEBUG_CATEGORY_GET (states, "GST_STATES");
362   fail_unless (states != NULL);
363
364   gst_debug_set_default_threshold (GST_LEVEL_WARNING);
365
366   gst_debug_set_threshold_for_name ("GST_STATES", GST_LEVEL_DEBUG);
367   cat1 = gst_debug_category_get_threshold (states);
368   gst_debug_unset_threshold_for_name ("GST_STATES");
369   cat2 = gst_debug_category_get_threshold (states);
370
371   gst_debug_set_default_threshold (orig);
372   fail_unless_equals_int (cat1, GST_LEVEL_DEBUG);
373   fail_unless_equals_int (cat2, GST_LEVEL_WARNING);
374 }
375
376 GST_END_TEST;
377
378 GST_START_TEST (info_set_and_unset_multiple)
379 {
380   GstDebugLevel orig = gst_debug_get_default_threshold ();
381   GstDebugLevel cat1, cat2, cat3;
382   GstDebugCategory *states;
383   GstDebugCategory *caps;
384
385   GST_DEBUG_CATEGORY_GET (states, "GST_STATES");
386   GST_DEBUG_CATEGORY_GET (caps, "GST_CAPS");
387   fail_unless (states != NULL);
388   fail_unless (caps != NULL);
389
390   gst_debug_set_default_threshold (GST_LEVEL_WARNING);
391
392   gst_debug_set_threshold_for_name ("GST_STATES", GST_LEVEL_DEBUG);
393   gst_debug_set_threshold_for_name ("GST_CAPS", GST_LEVEL_DEBUG);
394   cat1 = gst_debug_category_get_threshold (states);
395   gst_debug_unset_threshold_for_name ("GST_STATES");
396   gst_debug_unset_threshold_for_name ("GST_CAPS");
397   cat2 = gst_debug_category_get_threshold (states);
398   cat3 = gst_debug_category_get_threshold (caps);
399
400   gst_debug_set_default_threshold (orig);
401
402   fail_unless_equals_int (cat1, GST_LEVEL_DEBUG);
403   fail_unless_equals_int (cat2, GST_LEVEL_WARNING);
404   fail_unless_equals_int (cat3, GST_LEVEL_WARNING);
405 }
406
407 GST_END_TEST;
408 #endif
409
410 GST_START_TEST (info_fourcc)
411 {
412   gchar *res;
413   const gchar *cmp;
414
415   cmp = "abcd";
416   res = g_strdup_printf ("%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (0x64636261));
417   fail_unless_equals_string (res, cmp);
418   g_free (res);
419
420   cmp = ".bcd";
421   res = g_strdup_printf ("%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (0x646362a9));
422   fail_unless_equals_string (res, cmp);
423   g_free (res);
424 }
425
426 GST_END_TEST;
427
428 /* Here we're testing adding debug categories after gst_init() and making
429  * sure that this doesn't incur exponential costs. Previously this would
430  * reparse the debug string and re-add the parsed category/levels to the
431  * list, thus doubling the list to pattern match a category against for
432  * every category added. And we would also re-evaluate all existing categories
433  * against that list. This test makes sure the overhead of registering debug
434  * categories late is very small. This test would time out before the fix. */
435 GST_START_TEST (info_post_gst_init_category_registration)
436 {
437   GstDebugCategory *cats[10000] = { NULL, };
438   guint i;
439
440   /* Note: before the fixes this wouldn't work to trigger the problem because
441    * only a pattern set via GST_DEBUG before gst_init would be picked up
442    * (another bug) */
443   gst_debug_set_threshold_from_string ("*a*b:6,*b*0:6,*c:3,d*:2,xyz*:9,ax:1",
444       TRUE);
445
446   fail_unless_equals_int (GST_LEVEL_DEFAULT,
447       gst_debug_get_default_threshold ());
448
449   for (i = 0; i < G_N_ELEMENTS (cats); ++i) {
450     gchar *name = g_strdup_printf ("%s-%x", (i % 2 == 0) ? "cat" : "dog", i);
451     GST_DEBUG_CATEGORY_INIT (cats[i], name, 0, "none");
452     g_free (name);
453   }
454
455   /* These checks will only work if no one else set anything externally */
456   if (g_getenv ("GST_DEBUG") == NULL) {
457     /* none */
458     fail_unless_equals_int (gst_debug_category_get_threshold (cats[0]),
459         GST_LEVEL_DEFAULT);
460     /* d*:2 */
461     fail_unless_equals_int (gst_debug_category_get_threshold (cats[1]),
462         GST_LEVEL_WARNING);
463     /* none */
464     fail_unless_equals_int (gst_debug_category_get_threshold (cats[2]),
465         GST_LEVEL_DEFAULT);
466     /* d*:2 */
467     fail_unless_equals_int (gst_debug_category_get_threshold (cats[3]),
468         GST_LEVEL_WARNING);
469     /* *c:3 */
470     fail_unless_equals_int (gst_debug_category_get_threshold (cats[0xc]),
471         GST_LEVEL_FIXME);
472     /* *c:3 */
473     fail_unless_equals_int (gst_debug_category_get_threshold (cats[0x4c]),
474         GST_LEVEL_FIXME);
475     /* *a*b:6 and d*:2, but d*:2 takes priority here as cat name is "dog-a1b"
476      * and order matters: items listed later override earlier ones. */
477     fail_unless_equals_int (gst_debug_category_get_threshold (cats[0xa1b]),
478         GST_LEVEL_WARNING);
479     /* *a*0:6 */
480     fail_unless_equals_int (gst_debug_category_get_threshold (cats[0xb10]),
481         GST_LEVEL_LOG);
482   }
483
484   for (i = 0; i < G_N_ELEMENTS (cats); ++i)
485     gst_debug_category_free (cats[i]);
486 }
487
488 GST_END_TEST;
489
490 static Suite *
491 gst_info_suite (void)
492 {
493   Suite *s = suite_create ("GstInfo");
494   TCase *tc_chain = tcase_create ("info");
495
496   tcase_set_timeout (tc_chain, 30);
497
498   suite_add_tcase (s, tc_chain);
499   tcase_add_test (tc_chain, info_fourcc);
500 #ifndef GST_DISABLE_GST_DEBUG
501   tcase_add_test (tc_chain, info_segment_format_printf_extension);
502   tcase_add_test (tc_chain, info_ptr_format_printf_extension);
503   tcase_add_test (tc_chain, info_log_handler);
504   tcase_add_test (tc_chain, info_dump_mem);
505   tcase_add_test (tc_chain, info_fixme);
506   tcase_add_test (tc_chain, info_old_printf_extensions);
507   tcase_add_test (tc_chain, info_register_same_debug_category_twice);
508   tcase_add_test (tc_chain, info_set_and_unset_single);
509   tcase_add_test (tc_chain, info_set_and_unset_multiple);
510   tcase_add_test (tc_chain, info_post_gst_init_category_registration);
511 #endif
512
513   return s;
514 }
515
516 GST_CHECK_MAIN (gst_info);