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
printf_extension_log_func(GstDebugCategory * category,GstDebugLevel level,const gchar * file,const gchar * function,gint line,GObject * object,GstDebugMessage * message,gpointer unused)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 */
GST_START_TEST(info_ptr_format_printf_extension)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 */
GST_START_TEST(info_segment_format_printf_extension)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 
GST_START_TEST(info_log_handler)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 
GST_START_TEST(info_dump_mem)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 
GST_START_TEST(info_fixme)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
call_GST_INFO(const gchar * format,...)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 
GST_START_TEST(info_old_printf_extensions)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 
GST_START_TEST(info_register_same_debug_category_twice)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 
GST_START_TEST(info_set_and_unset_single)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 
GST_START_TEST(info_set_and_unset_multiple)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 
GST_START_TEST(info_fourcc)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. */
GST_START_TEST(info_post_gst_init_category_registration)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 *
gst_info_suite(void)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);
517