• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
231 static void
compare_gst_log_func(GstDebugCategory * category,GstDebugLevel level,const gchar * file,const gchar * function,gint line,GObject * object,GstDebugMessage * message,gpointer user_data)232 compare_gst_log_func (GstDebugCategory * category, GstDebugLevel level,
233     const gchar * file, const gchar * function, gint line, GObject * object,
234     GstDebugMessage * message, gpointer user_data)
235 {
236   gboolean match;
237   gchar *log_line;
238 
239   fail_unless_equals_pointer (user_data, NULL);
240 
241   log_line = gst_debug_log_get_line (category, level, file, function, line,
242       object, message);
243 
244   match = g_pattern_match_simple ("*:*:*.*0*DEBUG*check*gstinfo.c:*"
245       ":info_log_handler_get_line: test message\n", log_line);
246   fail_unless_equals_int (match, TRUE);
247   g_free (log_line);
248 }
249 
GST_START_TEST(info_log_handler_get_line)250 GST_START_TEST (info_log_handler_get_line)
251 {
252   gst_debug_remove_log_function (gst_debug_log_default);
253   gst_debug_add_log_function (compare_gst_log_func, NULL, NULL);
254 
255   gst_debug_set_default_threshold (GST_LEVEL_LOG);
256   GST_DEBUG ("test message");
257 
258   /* clean up */
259   gst_debug_set_default_threshold (GST_LEVEL_NONE);
260   gst_debug_add_log_function (gst_debug_log_default, NULL, NULL);
261   gst_debug_remove_log_function (compare_gst_log_func);
262 }
263 
264 GST_END_TEST;
265 
GST_START_TEST(info_dump_mem)266 GST_START_TEST (info_dump_mem)
267 {
268   GstDebugCategory *cat = NULL;
269   GstElement *e;
270 
271   const guint8 data[] = { 0x00, 0x00, 0x00, 0x20, 0x66, 0x74, 0x79, 0x70,
272     0x71, 0x74, 0x20, 0x20, 0x20, 0x05, 0x03, 0x00, 0x71, 0x74, 0x20, 0x20,
273     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
274     0x00, 0x00, 0xef, 0xe1, 0x6d, 0x6f, 0x6f, 0x76, 0x00, 0x00, 0x00, 0x6c,
275     0x6d, 0x76, 0x68, 0x64, 0x00, 0x00, 0x00, 0x00, 0xbf, 0xd1, 0x00, 0x1d,
276     0xbf, 0xd1, 0x00, 0x1e, 0x00, 0x00, 0x0b, 0xb5, 0x00, 0x04, 0x59, 0xc5,
277     0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
278     0x00, 0x00, 0x00, 0x00, 0x00, 0x01, '%', 's', '%', 's'
279   };
280 
281   e = gst_pipeline_new ("pipeline");
282   GST_DEBUG_CATEGORY_INIT (cat, "dumpcat", 0, "data dump debug category");
283   GST_MEMDUMP ("quicktime header", data, sizeof (data));
284   GST_MEMDUMP (NULL, data, sizeof (data));
285   GST_CAT_MEMDUMP (cat, "quicktime header", data, sizeof (data));
286   GST_MEMDUMP_OBJECT (e, "object stuff", data, sizeof (data));
287   GST_CAT_MEMDUMP_OBJECT (cat, e, "object/cat stuff", data, sizeof (data));
288   gst_object_unref (e);
289 }
290 
291 GST_END_TEST;
292 
GST_START_TEST(info_fixme)293 GST_START_TEST (info_fixme)
294 {
295   GstDebugCategory *cat = NULL;
296   GstElement *e;
297 
298   e = gst_pipeline_new ("pipeline");
299   GST_DEBUG_CATEGORY_INIT (cat, "fixcat", 0, "FIXME debug category");
300   GST_FIXME ("fix %s thing", "this");
301   GST_FIXME_OBJECT (e, "fix %s object", "this");
302   GST_CAT_FIXME (cat, "fix some%s in this category", "thing");
303   GST_CAT_FIXME_OBJECT (cat, e, "fix some%s in this cat and object", "thing");
304   gst_object_unref (e);
305 }
306 
307 GST_END_TEST;
308 
309 /* need this indirection so the compiler doesn't check the printf format
310  * like it would if we used GST_INFO directly (it would complain) */
311 static void
call_GST_INFO(const gchar * format,...)312 call_GST_INFO (const gchar * format, ...)
313 {
314   va_list var_args;
315 
316   va_start (var_args, format);
317   gst_debug_log_valist (GST_CAT_DEFAULT, GST_LEVEL_INFO, __FILE__, GST_FUNCTION,
318       __LINE__, NULL, format, var_args);
319   va_end (var_args);
320 }
321 
GST_START_TEST(info_old_printf_extensions)322 GST_START_TEST (info_old_printf_extensions)
323 {
324   GstSegment segment;
325   GstCaps *caps;
326   gchar *str;
327 
328   /* set up our own log function to make sure the code in gstinfo is actually
329    * executed without GST_DEBUG being set or it being output to stdout */
330   gst_debug_remove_log_function (gst_debug_log_default);
331   gst_debug_add_log_function (printf_extension_log_func, NULL, NULL);
332 
333   gst_debug_set_default_threshold (GST_LEVEL_LOG);
334 
335   save_messages = TRUE;
336 
337   fail_unless (messages == NULL);
338 
339   gst_segment_init (&segment, GST_FORMAT_TIME);
340   caps = gst_caps_new_simple ("foo/bar", "width", G_TYPE_INT, 4096,
341       "framerate", GST_TYPE_FRACTION, 50, 1, "format", G_TYPE_STRING, "ARGB",
342       NULL);
343   call_GST_INFO ("Segment %Q, caps are %P", &segment, caps);
344   gst_caps_unref (caps);
345 
346   fail_unless_equals_int (g_list_length (messages), 1);
347   str = (gchar *) messages->data;
348   fail_unless (str != NULL);
349 
350   GST_INFO ("str = '%s'", str);
351 
352   fail_unless (strstr (str, "time") != NULL);
353   fail_unless (strstr (str, "start=0:00:00.000000000") != NULL);
354   fail_unless (strstr (str, "stop=99:99:99.999999999") != NULL);
355   fail_unless (strstr (str, "applied_rate=1.000000") != NULL);
356 
357   fail_unless (strstr (str, " caps are ") != NULL);
358   fail_unless (strstr (str, "foo/bar") != NULL);
359   fail_unless (strstr (str, "width=(int)4096") != NULL);
360   fail_unless (strstr (str, "framerate=(fraction)50/1") != NULL);
361   fail_unless (strstr (str, "ARGB") != NULL);
362 
363   /* clean up */
364   gst_debug_set_default_threshold (GST_LEVEL_NONE);
365   gst_debug_add_log_function (gst_debug_log_default, NULL, NULL);
366   gst_debug_remove_log_function (printf_extension_log_func);
367   save_messages = FALSE;
368   g_list_free_full (messages, (GDestroyNotify) g_free);
369   messages = NULL;
370 }
371 
372 GST_END_TEST;
373 
GST_START_TEST(info_register_same_debug_category_twice)374 GST_START_TEST (info_register_same_debug_category_twice)
375 {
376   GstDebugCategory *cat1 = NULL, *cat2 = NULL;
377 
378   GST_DEBUG_CATEGORY_INIT (cat1, "dupli-cat", 0, "Going once");
379   GST_DEBUG_CATEGORY_INIT (cat2, "dupli-cat", 0, "Going twice");
380 
381   fail_unless_equals_pointer (cat1, cat2);
382 
383   fail_unless_equals_string (gst_debug_category_get_name (cat1), "dupli-cat");
384   fail_unless_equals_string (gst_debug_category_get_description (cat1),
385       "Going once");
386 }
387 
388 GST_END_TEST;
389 
GST_START_TEST(info_set_and_unset_single)390 GST_START_TEST (info_set_and_unset_single)
391 {
392   GstDebugLevel orig = gst_debug_get_default_threshold ();
393   GstDebugLevel cat1, cat2;
394   GstDebugCategory *states;
395 
396   GST_DEBUG_CATEGORY_GET (states, "GST_STATES");
397   fail_unless (states != NULL);
398 
399   gst_debug_set_default_threshold (GST_LEVEL_WARNING);
400 
401   gst_debug_set_threshold_for_name ("GST_STATES", GST_LEVEL_DEBUG);
402   cat1 = gst_debug_category_get_threshold (states);
403   gst_debug_unset_threshold_for_name ("GST_STATES");
404   cat2 = gst_debug_category_get_threshold (states);
405 
406   gst_debug_set_default_threshold (orig);
407   fail_unless_equals_int (cat1, GST_LEVEL_DEBUG);
408   fail_unless_equals_int (cat2, GST_LEVEL_WARNING);
409 }
410 
411 GST_END_TEST;
412 
GST_START_TEST(info_set_and_unset_multiple)413 GST_START_TEST (info_set_and_unset_multiple)
414 {
415   GstDebugLevel orig = gst_debug_get_default_threshold ();
416   GstDebugLevel cat1, cat2, cat3;
417   GstDebugCategory *states;
418   GstDebugCategory *caps;
419 
420   GST_DEBUG_CATEGORY_GET (states, "GST_STATES");
421   GST_DEBUG_CATEGORY_GET (caps, "GST_CAPS");
422   fail_unless (states != NULL);
423   fail_unless (caps != NULL);
424 
425   gst_debug_set_default_threshold (GST_LEVEL_WARNING);
426 
427   gst_debug_set_threshold_for_name ("GST_STATES", GST_LEVEL_DEBUG);
428   gst_debug_set_threshold_for_name ("GST_CAPS", GST_LEVEL_DEBUG);
429   cat1 = gst_debug_category_get_threshold (states);
430   gst_debug_unset_threshold_for_name ("GST_STATES");
431   gst_debug_unset_threshold_for_name ("GST_CAPS");
432   cat2 = gst_debug_category_get_threshold (states);
433   cat3 = gst_debug_category_get_threshold (caps);
434 
435   gst_debug_set_default_threshold (orig);
436 
437   fail_unless_equals_int (cat1, GST_LEVEL_DEBUG);
438   fail_unless_equals_int (cat2, GST_LEVEL_WARNING);
439   fail_unless_equals_int (cat3, GST_LEVEL_WARNING);
440 }
441 
442 GST_END_TEST;
443 #endif
444 
GST_START_TEST(info_fourcc)445 GST_START_TEST (info_fourcc)
446 {
447   gchar *res;
448   const gchar *cmp;
449 
450   cmp = "abcd";
451   res = g_strdup_printf ("%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (0x64636261));
452   fail_unless_equals_string (res, cmp);
453   g_free (res);
454 
455   cmp = ".bcd";
456   res = g_strdup_printf ("%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (0x646362a9));
457   fail_unless_equals_string (res, cmp);
458   g_free (res);
459 }
460 
461 GST_END_TEST;
462 
463 /* Here we're testing adding debug categories after gst_init() and making
464  * sure that this doesn't incur exponential costs. Previously this would
465  * reparse the debug string and re-add the parsed category/levels to the
466  * list, thus doubling the list to pattern match a category against for
467  * every category added. And we would also re-evaluate all existing categories
468  * against that list. This test makes sure the overhead of registering debug
469  * categories late is very small. This test would time out before the fix. */
GST_START_TEST(info_post_gst_init_category_registration)470 GST_START_TEST (info_post_gst_init_category_registration)
471 {
472   GstDebugCategory *cats[10000] = { NULL, };
473   guint i;
474 
475   /* Note: before the fixes this wouldn't work to trigger the problem because
476    * only a pattern set via GST_DEBUG before gst_init would be picked up
477    * (another bug) */
478   gst_debug_set_threshold_from_string ("*a*b:6,*b*0:6,*c:3,d*:2,xyz*:9,ax:1",
479       TRUE);
480 
481   fail_unless_equals_int (GST_LEVEL_DEFAULT,
482       gst_debug_get_default_threshold ());
483 
484   for (i = 0; i < G_N_ELEMENTS (cats); ++i) {
485     gchar *name = g_strdup_printf ("%s-%x", (i % 2 == 0) ? "cat" : "dog", i);
486     GST_DEBUG_CATEGORY_INIT (cats[i], name, 0, "none");
487     g_free (name);
488   }
489 
490   /* These checks will only work if no one else set anything externally */
491   if (g_getenv ("GST_DEBUG") == NULL) {
492     /* none */
493     fail_unless_equals_int (gst_debug_category_get_threshold (cats[0]),
494         GST_LEVEL_DEFAULT);
495     /* d*:2 */
496     fail_unless_equals_int (gst_debug_category_get_threshold (cats[1]),
497         GST_LEVEL_WARNING);
498     /* none */
499     fail_unless_equals_int (gst_debug_category_get_threshold (cats[2]),
500         GST_LEVEL_DEFAULT);
501     /* d*:2 */
502     fail_unless_equals_int (gst_debug_category_get_threshold (cats[3]),
503         GST_LEVEL_WARNING);
504     /* *c:3 */
505     fail_unless_equals_int (gst_debug_category_get_threshold (cats[0xc]),
506         GST_LEVEL_FIXME);
507     /* *c:3 */
508     fail_unless_equals_int (gst_debug_category_get_threshold (cats[0x4c]),
509         GST_LEVEL_FIXME);
510     /* *a*b:6 and d*:2, but d*:2 takes priority here as cat name is "dog-a1b"
511      * and order matters: items listed later override earlier ones. */
512     fail_unless_equals_int (gst_debug_category_get_threshold (cats[0xa1b]),
513         GST_LEVEL_WARNING);
514     /* *a*0:6 */
515     fail_unless_equals_int (gst_debug_category_get_threshold (cats[0xb10]),
516         GST_LEVEL_LOG);
517   }
518 }
519 
520 GST_END_TEST;
521 
522 static Suite *
gst_info_suite(void)523 gst_info_suite (void)
524 {
525   Suite *s = suite_create ("GstInfo");
526   TCase *tc_chain = tcase_create ("info");
527 
528   tcase_set_timeout (tc_chain, 30);
529 
530   suite_add_tcase (s, tc_chain);
531   tcase_add_test (tc_chain, info_fourcc);
532 #ifndef GST_DISABLE_GST_DEBUG
533   tcase_add_test (tc_chain, info_segment_format_printf_extension);
534   tcase_add_test (tc_chain, info_ptr_format_printf_extension);
535   tcase_add_test (tc_chain, info_log_handler);
536   tcase_add_test (tc_chain, info_log_handler_get_line);
537   tcase_add_test (tc_chain, info_dump_mem);
538   tcase_add_test (tc_chain, info_fixme);
539   tcase_add_test (tc_chain, info_old_printf_extensions);
540   tcase_add_test (tc_chain, info_register_same_debug_category_twice);
541   tcase_add_test (tc_chain, info_set_and_unset_single);
542   tcase_add_test (tc_chain, info_set_and_unset_multiple);
543   tcase_add_test (tc_chain, info_post_gst_init_category_registration);
544 #endif
545 
546   return s;
547 }
548 
549 GST_CHECK_MAIN (gst_info);
550