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