2 * Copyright (C) <2005> Thomas Vander Stichele <thomas at apestaart dot org>
4 * gststructure.c: Unit tests for GstStructure
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
23 #include <gst/gststructure.h>
24 #include <gst/check/gstcheck.h>
27 GST_START_TEST (test_from_string_int)
29 const char *strings[] = {
30 "video/x-raw, width = (int) 123456",
31 "video/x-raw, stride = (int) -123456",
32 "video/x-raw, red_mask = (int) 0xFFFF",
33 "video/x-raw, red_mask = (int) 0x0000FFFF",
34 "video/x-raw, red_mask = (int) 0x7FFFFFFF",
35 "video/x-raw, red_mask = (int) 0x80000000",
36 "video/x-raw, red_mask = (int) 0xFF000000",
38 * gst-launch ... ! "video/x-raw, red_mask=(int)0xFF000000" ! ... */
39 "video/x-raw,\\ red_mask=(int)0xFF000000",
51 GstStructure *structure;
54 for (i = 0; i < G_N_ELEMENTS (strings); ++i) {
61 structure = gst_structure_from_string (s, NULL);
62 fail_if (structure == NULL, "Could not get structure from string %s", s);
63 name = gst_structure_nth_field_name (structure, 0);
64 fail_unless (gst_structure_get_int (structure, name, &value));
65 fail_unless (value == results[i],
66 "Value %d is not the expected result %d for string %s",
67 value, results[i], s);
70 gst_structure_free (structure);
76 GST_START_TEST (test_from_string_uint)
78 const char *strings[] = {
79 "taglist, bar = (uint) 123456",
80 "taglist, bar = (uint) 0xFFFF",
81 "taglist, bar = (uint) 0x0000FFFF",
82 "taglist, bar = (uint) 0x7FFFFFFF",
83 "taglist, bar = (uint) 0x80000000",
84 "taglist, bar = (uint) 0xFF000000"
94 GstStructure *structure;
97 for (i = 0; i < G_N_ELEMENTS (strings); ++i) {
104 structure = gst_structure_from_string (s, NULL);
105 fail_if (structure == NULL, "Could not get structure from string %s", s);
106 name = gst_structure_nth_field_name (structure, 0);
107 fail_unless (gst_structure_get_uint (structure, name, &value));
108 fail_unless (value == results[i],
109 "Value %u is not the expected result %u for string %s",
110 value, results[i], s);
113 gst_structure_free (structure);
119 /* Test type conversions from string */
120 GST_START_TEST (test_from_string)
122 GstStructure *structure;
126 s = "test-string,value=1";
127 structure = gst_structure_from_string (s, NULL);
128 fail_if (structure == NULL, "Could not get structure from string %s", s);
129 fail_unless ((val = gst_structure_get_value (structure, "value")) != NULL);
130 fail_unless (G_VALUE_HOLDS_INT (val));
131 gst_structure_free (structure);
133 s = "test-string,value=1.0";
134 structure = gst_structure_from_string (s, NULL);
135 fail_if (structure == NULL, "Could not get structure from string %s", s);
136 fail_unless ((val = gst_structure_get_value (structure, "value")) != NULL);
137 fail_unless (G_VALUE_HOLDS_DOUBLE (val));
138 gst_structure_free (structure);
140 s = "test-string,value=1/1";
141 structure = gst_structure_from_string (s, NULL);
142 fail_if (structure == NULL, "Could not get structure from string %s", s);
143 fail_unless ((val = gst_structure_get_value (structure, "value")) != NULL);
144 fail_unless (GST_VALUE_HOLDS_FRACTION (val));
145 gst_structure_free (structure);
147 s = "test-string,value=bar";
148 structure = gst_structure_from_string (s, NULL);
149 fail_if (structure == NULL, "Could not get structure from string %s", s);
150 fail_unless ((val = gst_structure_get_value (structure, "value")) != NULL);
151 fail_unless (G_VALUE_HOLDS_STRING (val));
152 gst_structure_free (structure);
154 s = "test-string,value=true";
155 structure = gst_structure_from_string (s, NULL);
156 fail_if (structure == NULL, "Could not get structure from string %s", s);
157 fail_unless ((val = gst_structure_get_value (structure, "value")) != NULL);
158 fail_unless (G_VALUE_HOLDS_BOOLEAN (val));
159 fail_unless_equals_int (g_value_get_boolean (val), TRUE);
160 gst_structure_free (structure);
162 s = "0.10:decoder-video/mpeg, abc=(boolean)false";
163 ASSERT_CRITICAL (structure = gst_structure_from_string (s, NULL));
164 fail_unless (structure == NULL, "Could not get structure from string %s", s);
166 /* make sure we bail out correctly in case of an error or if parsing fails */
167 s = "***foo***, abc=(boolean)false";
168 structure = gst_structure_from_string (s, NULL);
169 fail_unless (structure == NULL);
171 /* assert that we get a warning if the structure wasn't entirely consumed, but
172 * we didn't provide an end pointer */
173 s = "foo/bar; other random data";
174 ASSERT_WARNING (structure = gst_structure_from_string (s, NULL));
175 fail_if (structure == NULL, "Could not get structure from string %s", s);
176 gst_structure_free (structure);
178 /* make sure we handle \ as last character in various things, run with valgrind */
179 s = "foo,test=\"foobar\\";
180 structure = gst_structure_from_string (s, NULL);
181 fail_unless (structure == NULL);
183 structure = gst_structure_from_string (s, NULL);
184 fail_unless (structure == NULL);
186 structure = gst_structure_from_string (s, NULL);
187 fail_unless (structure == NULL);
188 s = "foobar,test=(string)foo\\";
189 structure = gst_structure_from_string (s, NULL);
190 fail_unless (structure == NULL);
196 GST_START_TEST (test_to_string)
200 ASSERT_CRITICAL (st1 = gst_structure_new_empty ("Foo\nwith-newline"));
201 fail_unless (st1 == NULL);
203 ASSERT_CRITICAL (st1 = gst_structure_new_empty ("Foo with whitespace"));
204 fail_unless (st1 == NULL);
205 ASSERT_CRITICAL (st1 = gst_structure_new_empty ("1st"));
206 fail_unless (st1 == NULL);
212 GST_START_TEST (test_to_from_string)
214 GstCaps *caps1, *caps2;
215 GstStructure *st1, *st2;
216 gchar *str, *res1, *res2;
218 /* test escaping/unescaping */
219 st1 = gst_structure_new ("FooBar-123/0_1", "num", G_TYPE_INT, 9173,
220 "string", G_TYPE_STRING, "Something Like Face/Off", NULL);
221 str = gst_structure_to_string (st1);
222 st2 = gst_structure_from_string (str, NULL);
225 fail_unless (st2 != NULL);
227 /* need to put structures into caps to compare */
228 caps1 = gst_caps_new_empty ();
229 gst_caps_append_structure (caps1, st1);
230 caps2 = gst_caps_new_empty ();
231 gst_caps_append_structure (caps2, st2);
232 res1 = gst_caps_to_string (caps1);
233 res2 = gst_caps_to_string (caps2);
234 fail_unless (gst_caps_is_equal (caps1, caps2),
235 "Structures did not match:\n\tStructure 1: %s\n\tStructure 2: %s\n",
237 gst_caps_unref (caps1);
238 gst_caps_unref (caps2);
245 /* Added to make sure taglists are properly serialized/deserialized after bug
246 * https://bugzilla.gnome.org/show_bug.cgi?id=733131 */
247 GST_START_TEST (test_to_from_string_tag_event)
251 GstStructure *st1, *st2;
255 taglist = gst_tag_list_new_empty ();
256 tagevent = gst_event_new_tag (taglist);
258 st1 = (GstStructure *) gst_event_get_structure (tagevent);
259 str = gst_structure_to_string (st1);
260 fail_unless (str != NULL);
262 st2 = gst_structure_new_from_string (str);
263 fail_unless (st2 != NULL);
264 fail_unless (gst_structure_is_equal (st1, st2));
265 gst_event_unref (tagevent);
266 gst_structure_free (st2);
269 /* taglist with data */
270 taglist = gst_tag_list_new ("title", "TEST TITLE", NULL);
271 tagevent = gst_event_new_tag (taglist);
273 st1 = (GstStructure *) gst_event_get_structure (tagevent);
274 str = gst_structure_to_string (st1);
275 fail_unless (str != NULL);
277 st2 = gst_structure_new_from_string (str);
278 fail_unless (st2 != NULL);
279 fail_unless (gst_structure_is_equal (st1, st2));
280 gst_event_unref (tagevent);
281 gst_structure_free (st2);
287 GST_START_TEST (test_complete_structure)
289 GstStructure *structure;
292 s = "GstEventSeek, rate=(double)1, format=(GstFormat)GST_FORMAT_TIME, flags=(GstSeekFlags)GST_SEEK_FLAGS_NONE, start_type=(GstSeekType)GST_SEEK_TYPE_SET, start=(gint64)1000000000, stop_type=(GstSeekType)GST_SEEK_TYPE_NONE, stop=(gint64)0";
293 structure = gst_structure_from_string (s, NULL);
294 fail_if (structure == NULL, "Could not get structure from string %s", s);
295 /* FIXME: TODO: add checks for correct serialization of members ? */
296 gst_structure_free (structure);
301 GST_START_TEST (test_string_properties)
303 GstCaps *caps1, *caps2;
304 GstStructure *st1, *st2;
305 gchar *str, *res1, *res2;
307 /* test escaping/unescaping */
308 st1 = gst_structure_new ("RandomStructure", "prop1", G_TYPE_STRING, "foo",
309 "prop2", G_TYPE_STRING, "", "prop3", G_TYPE_STRING, NULL,
310 "prop4", G_TYPE_STRING, "NULL", NULL);
311 str = gst_structure_to_string (st1);
312 st2 = gst_structure_from_string (str, NULL);
315 fail_unless (st2 != NULL);
317 /* need to put structures into caps to compare */
318 caps1 = gst_caps_new_empty ();
319 gst_caps_append_structure (caps1, st1);
320 caps2 = gst_caps_new_empty ();
321 gst_caps_append_structure (caps2, st2);
322 res1 = gst_caps_to_string (caps1);
323 res2 = gst_caps_to_string (caps2);
324 fail_unless (gst_caps_is_equal (caps1, caps2),
325 "Structures did not match:\n\tStructure 1: %s\n\tStructure 2: %s\n",
327 gst_caps_unref (caps1);
328 gst_caps_unref (caps2);
335 GST_START_TEST (test_structure_new)
342 GstClockTime clocktime;
345 s = gst_structure_new ("name",
346 "key", G_TYPE_STRING, "value",
347 "bool", G_TYPE_BOOLEAN, TRUE,
348 "fraction", GST_TYPE_FRACTION, 1, 5,
349 "clocktime", GST_TYPE_CLOCK_TIME, GST_CLOCK_TIME_NONE,
350 "uint64", G_TYPE_UINT64, (guint64) 1234, NULL);
352 fail_unless (gst_structure_get_field_type (s, "unknown") == G_TYPE_INVALID);
353 /* test setting a different name */
354 gst_structure_set_name (s, "newname");
355 fail_unless (strcmp (gst_structure_get_string (s, "key"), "value") == 0);
356 fail_unless (gst_structure_has_field (s, "key"));
357 fail_unless_equals_int (gst_structure_n_fields (s), 5);
358 /* test removing a field */
359 gst_structure_remove_field (s, "key");
360 fail_if (gst_structure_get_string (s, "key"));
361 fail_if (gst_structure_has_field (s, "key"));
362 fail_unless_equals_int (gst_structure_n_fields (s), 4);
364 fail_unless (gst_structure_get_boolean (s, "bool", &bool));
367 fail_unless (gst_structure_get_fraction (s, "fraction", &num, &den));
368 fail_unless_equals_int (num, 1);
369 fail_unless_equals_int (den, 5);
371 fail_unless (gst_structure_get_clock_time (s, "clocktime", &clocktime));
372 fail_unless_equals_uint64 (clocktime, GST_CLOCK_TIME_NONE);
374 fail_unless (gst_structure_get_uint64 (s, "uint64", &uint64));
375 fail_unless_equals_uint64 (uint64, 1234);
377 gst_structure_free (s);
379 domain = g_quark_from_static_string ("test");
380 e = g_error_new (domain, 0, "a test error");
381 s = gst_structure_new ("name", "key", G_TYPE_ERROR, e, NULL);
383 gst_structure_free (s);
385 ASSERT_CRITICAL (gst_structure_free (gst_structure_new_empty
386 ("0.10:decoder-video/mpeg")));
388 /* make sure we bail out correctly in case of an error or if parsing fails */
389 ASSERT_CRITICAL (s = gst_structure_new ("^joo\nba\ndoo^",
390 "abc", G_TYPE_BOOLEAN, FALSE, NULL));
391 fail_unless (s == NULL);
396 GST_START_TEST (test_fixate)
400 s = gst_structure_new ("name",
401 "int", G_TYPE_INT, 5,
402 "intrange", GST_TYPE_INT_RANGE, 5, 10,
403 "intrange2", GST_TYPE_INT_RANGE, 5, 10, NULL);
405 fail_if (gst_structure_fixate_field_nearest_int (s, "int", 5));
406 fail_unless (gst_structure_fixate_field_nearest_int (s, "intrange", 5));
407 fail_if (gst_structure_fixate_field_nearest_int (s, "intrange", 5));
408 fail_unless (gst_structure_fixate_field_nearest_int (s, "intrange2", 15));
409 fail_if (gst_structure_fixate_field_nearest_int (s, "intrange2", 15));
410 gst_structure_free (s);
415 GST_START_TEST (test_fixate_frac_list)
417 GstStructure *s, *s2;
423 g_value_init (&list, GST_TYPE_LIST);
424 g_value_init (&frac, GST_TYPE_FRACTION);
426 gst_value_set_fraction (&frac, 30, 1);
427 gst_value_list_append_value (&list, &frac);
428 gst_value_set_fraction (&frac, 15, 1);
429 gst_value_list_append_value (&list, &frac);
430 gst_value_set_fraction (&frac, 10, 1);
431 gst_value_list_append_value (&list, &frac);
433 s = gst_structure_new_empty ("name");
434 gst_structure_set_value (s, "frac", &list);
435 g_value_unset (&frac);
436 g_value_unset (&list);
438 str = gst_structure_to_string (s);
439 GST_DEBUG ("list %s", str);
443 s2 = gst_structure_copy (s);
445 /* fixate to the nearest fraction, this should give 15/1 */
446 fail_unless (gst_structure_fixate_field_nearest_fraction (s, "frac", 14, 1));
448 fail_unless (gst_structure_get_fraction (s, "frac", &num, &denom));
449 fail_unless (num == 15);
450 fail_unless (denom == 1);
452 gst_structure_free (s);
455 /* fixate to the nearest fraction, this should give 30/1 */
456 fail_unless (gst_structure_fixate_field_nearest_fraction (s, "frac", G_MAXINT,
459 fail_unless (gst_structure_get_fraction (s, "frac", &num, &denom));
460 fail_unless (num == 30);
461 fail_unless (denom == 1);
462 gst_structure_free (s);
467 GST_START_TEST (test_is_subset)
469 GstStructure *s1, *s2;
471 s1 = gst_structure_from_string ("test/test, channels=(int){ 1, 2 }", NULL);
472 fail_if (s1 == NULL);
473 s2 = gst_structure_from_string ("test/test, channels=(int)[ 1, 2 ]", NULL);
474 fail_if (s2 == NULL);
476 fail_unless (gst_structure_is_subset (s1, s2));
478 gst_structure_free (s1);
479 gst_structure_free (s2);
485 GST_START_TEST (test_structure_nested)
487 GstStructure *sp, *sc1, *sc2;
490 sc1 = gst_structure_new ("Camera",
491 "XResolution", G_TYPE_INT, 72, "YResolution", G_TYPE_INT, 73, NULL);
492 fail_unless (sc1 != NULL);
494 sc2 = gst_structure_new ("Image-Data",
495 "Orientation", G_TYPE_STRING, "top-left",
496 "Comment", G_TYPE_STRING, "super photo", NULL);
497 fail_unless (sc2 != NULL);
499 sp = gst_structure_new ("Exif", "Camera", GST_TYPE_STRUCTURE, sc1,
500 "Image Data", GST_TYPE_STRUCTURE, sc2, NULL);
501 fail_unless (sp != NULL);
503 fail_unless (gst_structure_n_fields (sp) == 2);
505 fail_unless (gst_structure_has_field_typed (sp, "Camera",
506 GST_TYPE_STRUCTURE));
508 str = gst_structure_to_string (sp);
509 fail_unless (str != NULL);
511 GST_DEBUG ("serialized to '%s'", str);
513 fail_unless (g_str_equal (str,
515 ", Camera=(structure)\"Camera\\,\\ XResolution\\=\\(int\\)72\\,\\ YResolution\\=\\(int\\)73\\;\""
516 ", Image Data=(structure)\"Image-Data\\,\\ Orientation\\=\\(string\\)top-left\\,\\ Comment\\=\\(string\\)\\\"super\\\\\\ photo\\\"\\;\";"));
521 gst_structure_free (sc1);
522 gst_structure_free (sc2);
523 gst_structure_free (sp);
528 GST_START_TEST (test_structure_nested_from_and_to_string)
532 gchar *str2, *end = NULL;
535 ", main-sub1=(structure)\"type-b\\,\\ machine-type\\=\\(int\\)0\\;\""
536 ", main-sub2=(structure)\"type-a\\,\\ plugin-filename\\=\\(string\\)\\\"/home/user/lib/lib\\\\\\ with\\\\\\ spaces.dll\\\"\\,\\ machine-type\\=\\(int\\)1\\;\""
537 ", main-sub3=(structure)\"type-b\\,\\ plugin-filename\\=\\(string\\)/home/user/lib/lib_no_spaces.so\\,\\ machine-type\\=\\(int\\)1\\;\""
540 s = gst_structure_from_string (str1, &end);
541 fail_unless (s != NULL);
543 GST_DEBUG ("not parsed part : %s", end);
544 fail_unless (*end == '\0');
546 fail_unless (gst_structure_n_fields (s) == 3);
548 fail_unless (gst_structure_has_field_typed (s, "main-sub1",
549 GST_TYPE_STRUCTURE));
551 str2 = gst_structure_to_string (s);
552 fail_unless (str2 != NULL);
554 fail_unless (g_str_equal (str1, str2));
558 gst_structure_free (s);
563 GST_START_TEST (test_vararg_getters)
566 GstBuffer *buf, *buf2;
568 GstCaps *caps, *caps2;
576 buf = gst_buffer_new_and_alloc (3);
578 fail_unless (gst_buffer_map (buf, &info, GST_MAP_WRITE));
583 gst_buffer_unmap (buf, &info);
585 caps = gst_caps_new_empty_simple ("video/x-foo");
587 s = gst_structure_new ("test", "int", G_TYPE_INT, 12345678, "string",
588 G_TYPE_STRING, "Hello World!", "buf", GST_TYPE_BUFFER, buf, "caps",
589 GST_TYPE_CAPS, caps, "int64", G_TYPE_INT64, G_GINT64_CONSTANT (-99),
590 "double", G_TYPE_DOUBLE, G_MAXDOUBLE, "frag", GST_TYPE_FRACTION, 39, 14,
593 /* first the plain one */
594 ret = gst_structure_get (s, "double", G_TYPE_DOUBLE, &d, "string",
595 G_TYPE_STRING, &c, "caps", GST_TYPE_CAPS, &caps2, "buf",
596 GST_TYPE_BUFFER, &buf2, "frag", GST_TYPE_FRACTION, &num, &denom, "int",
597 G_TYPE_INT, &i, "int64", G_TYPE_INT64, &i64, NULL);
600 fail_unless_equals_string (c, "Hello World!");
601 fail_unless_equals_int (i, 12345678);
602 fail_unless_equals_float (d, G_MAXDOUBLE);
603 fail_unless_equals_int (num, 39);
604 fail_unless_equals_int (denom, 14);
605 fail_unless (i64 == -99);
606 fail_unless (caps == caps2);
607 fail_unless (buf == buf2);
609 /* expected failures */
610 ASSERT_CRITICAL (gst_structure_get (s, NULL, G_TYPE_INT, &i, NULL));
611 fail_if (gst_structure_get (s, "int", G_TYPE_INT, &i, "double",
612 G_TYPE_FLOAT, &d, NULL));
613 fail_if (gst_structure_get (s, "int", G_TYPE_INT, &i, "dooble",
614 G_TYPE_DOUBLE, &d, NULL));
618 gst_caps_unref (caps2);
620 gst_buffer_unref (buf2);
623 /* and now the _id variant */
624 ret = gst_structure_id_get (s, g_quark_from_static_string ("double"),
625 G_TYPE_DOUBLE, &d, g_quark_from_static_string ("string"), G_TYPE_STRING,
626 &c, g_quark_from_static_string ("caps"), GST_TYPE_CAPS, &caps2,
627 g_quark_from_static_string ("buf"), GST_TYPE_BUFFER, &buf2,
628 g_quark_from_static_string ("int"), G_TYPE_INT, &i,
629 g_quark_from_static_string ("int64"), G_TYPE_INT64, &i64, NULL);
632 fail_unless_equals_string (c, "Hello World!");
633 fail_unless_equals_int (i, 12345678);
634 fail_unless_equals_float (d, G_MAXDOUBLE);
635 fail_unless (i64 == -99);
636 fail_unless (caps == caps2);
637 fail_unless (buf == buf2);
639 /* expected failures */
640 ASSERT_CRITICAL (gst_structure_get (s, 0, G_TYPE_INT, &i, NULL));
641 fail_if (gst_structure_id_get (s, g_quark_from_static_string ("int"),
642 G_TYPE_INT, &i, g_quark_from_static_string ("double"), G_TYPE_FLOAT,
644 fail_if (gst_structure_id_get (s, g_quark_from_static_string ("int"),
645 G_TYPE_INT, &i, g_quark_from_static_string ("dooble"), G_TYPE_DOUBLE,
649 gst_caps_unref (caps2);
650 gst_buffer_unref (buf2);
652 /* finally make sure NULL as return location is handled gracefully */
653 ret = gst_structure_get (s, "double", G_TYPE_DOUBLE, NULL, "string",
654 G_TYPE_STRING, NULL, "caps", GST_TYPE_CAPS, NULL, "buf",
655 GST_TYPE_BUFFER, NULL, "int", G_TYPE_INT, &i, "frag", GST_TYPE_FRACTION,
656 NULL, NULL, "int64", G_TYPE_INT64, &i64, NULL);
658 ASSERT_WARNING (gst_structure_get (s, "frag", GST_TYPE_FRACTION, NULL,
660 ASSERT_WARNING (gst_structure_get (s, "frag", GST_TYPE_FRACTION, &num,
664 gst_caps_unref (caps);
665 gst_buffer_unref (buf);
666 gst_structure_free (s);
672 gst_structure_suite (void)
674 Suite *s = suite_create ("GstStructure");
675 TCase *tc_chain = tcase_create ("general");
677 suite_add_tcase (s, tc_chain);
678 tcase_add_test (tc_chain, test_from_string_int);
679 tcase_add_test (tc_chain, test_from_string_uint);
680 tcase_add_test (tc_chain, test_from_string);
681 tcase_add_test (tc_chain, test_to_string);
682 tcase_add_test (tc_chain, test_to_from_string);
683 tcase_add_test (tc_chain, test_to_from_string_tag_event);
684 tcase_add_test (tc_chain, test_string_properties);
685 tcase_add_test (tc_chain, test_complete_structure);
686 tcase_add_test (tc_chain, test_structure_new);
687 tcase_add_test (tc_chain, test_fixate);
688 tcase_add_test (tc_chain, test_fixate_frac_list);
689 tcase_add_test (tc_chain, test_is_subset);
690 tcase_add_test (tc_chain, test_structure_nested);
691 tcase_add_test (tc_chain, test_structure_nested_from_and_to_string);
692 tcase_add_test (tc_chain, test_vararg_getters);
696 GST_CHECK_MAIN (gst_structure);