07fea67949dc3c575f0c9f9ee2b59aac6f667216
[platform/upstream/gstreamer.git] / tests / check / gst / gststructure.c
1 /* GStreamer
2  * Copyright (C) <2005> Thomas Vander Stichele <thomas at apestaart dot org>
3  *
4  * gststructure.c: Unit tests for GstStructure
5  *
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.
10  *
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.
15  *
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.
20  */
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <gst/gststructure.h>
26 #include <gst/check/gstcheck.h>
27
28
29 GST_START_TEST (test_from_string_int)
30 {
31   const char *strings[] = {
32     "video/x-raw, width = (int) 123456",
33     "video/x-raw, stride = (int) -123456",
34     "video/x-raw, red_mask = (int) 0xFFFF",
35     "video/x-raw, red_mask = (int) 0x0000FFFF",
36     "video/x-raw, red_mask = (int) 0x7FFFFFFF",
37     "video/x-raw, red_mask = (int) 0x80000000",
38     "video/x-raw, red_mask = (int) 0xFF000000",
39     /* result from
40      * gst-launch ... ! "video/x-raw, red_mask=(int)0xFF000000" ! ... */
41     "video/x-raw,\\ red_mask=(int)0xFF000000",
42   };
43   gint results[] = {
44     123456,
45     -123456,
46     0xFFFF,
47     0xFFFF,
48     0x7FFFFFFF,
49     (gint) 0x80000000,
50     (gint) 0xFF000000,
51     (gint) 0xFF000000,
52   };
53   GstStructure *structure;
54   int i;
55
56   for (i = 0; i < G_N_ELEMENTS (strings); ++i) {
57     const char *s;
58     const gchar *name;
59     gint value;
60
61     s = strings[i];
62
63     structure = gst_structure_from_string (s, NULL);
64     fail_if (structure == NULL, "Could not get structure from string %s", s);
65     name = gst_structure_nth_field_name (structure, 0);
66     fail_unless (gst_structure_get_int (structure, name, &value));
67     fail_unless (value == results[i],
68         "Value %d is not the expected result %d for string %s",
69         value, results[i], s);
70
71     /* cleanup */
72     gst_structure_free (structure);
73   }
74 }
75
76 GST_END_TEST;
77
78 GST_START_TEST (test_from_string_uint)
79 {
80   const char *strings[] = {
81     "taglist, bar = (uint) 123456",
82     "taglist, bar = (uint) 0xFFFF",
83     "taglist, bar = (uint) 0x0000FFFF",
84     "taglist, bar = (uint) 0x7FFFFFFF",
85     "taglist, bar = (uint) 0x80000000",
86     "taglist, bar = (uint) 0xFF000000"
87   };
88   guint results[] = {
89     123456,
90     0xFFFF,
91     0xFFFF,
92     0x7FFFFFFF,
93     0x80000000,
94     0xFF000000,
95   };
96   GstStructure *structure;
97   int i;
98
99   for (i = 0; i < G_N_ELEMENTS (strings); ++i) {
100     const char *s;
101     const gchar *name;
102     guint value;
103
104     s = strings[i];
105
106     structure = gst_structure_from_string (s, NULL);
107     fail_if (structure == NULL, "Could not get structure from string %s", s);
108     name = gst_structure_nth_field_name (structure, 0);
109     fail_unless (gst_structure_get_uint (structure, name, &value));
110     fail_unless (value == results[i],
111         "Value %u is not the expected result %u for string %s",
112         value, results[i], s);
113
114     /* cleanup */
115     gst_structure_free (structure);
116   }
117 }
118
119 GST_END_TEST;
120
121 /* Test type conversions from string */
122 GST_START_TEST (test_from_string)
123 {
124   GstStructure *structure;
125   const gchar *s;
126   const GValue *val;
127
128   s = "test-string,value=1";
129   structure = gst_structure_from_string (s, NULL);
130   fail_if (structure == NULL, "Could not get structure from string %s", s);
131   fail_unless ((val = gst_structure_get_value (structure, "value")) != NULL);
132   fail_unless (G_VALUE_HOLDS_INT (val));
133   gst_structure_free (structure);
134
135   s = "test-string,value=1.0";
136   structure = gst_structure_from_string (s, NULL);
137   fail_if (structure == NULL, "Could not get structure from string %s", s);
138   fail_unless ((val = gst_structure_get_value (structure, "value")) != NULL);
139   fail_unless (G_VALUE_HOLDS_DOUBLE (val));
140   gst_structure_free (structure);
141
142   s = "test-string,value=1/1";
143   structure = gst_structure_from_string (s, NULL);
144   fail_if (structure == NULL, "Could not get structure from string %s", s);
145   fail_unless ((val = gst_structure_get_value (structure, "value")) != NULL);
146   fail_unless (GST_VALUE_HOLDS_FRACTION (val));
147   gst_structure_free (structure);
148
149   s = "test-string,value=bar";
150   structure = gst_structure_from_string (s, NULL);
151   fail_if (structure == NULL, "Could not get structure from string %s", s);
152   fail_unless ((val = gst_structure_get_value (structure, "value")) != NULL);
153   fail_unless (G_VALUE_HOLDS_STRING (val));
154   gst_structure_free (structure);
155
156   s = "test-string,value=true";
157   structure = gst_structure_from_string (s, NULL);
158   fail_if (structure == NULL, "Could not get structure from string %s", s);
159   fail_unless ((val = gst_structure_get_value (structure, "value")) != NULL);
160   fail_unless (G_VALUE_HOLDS_BOOLEAN (val));
161   fail_unless_equals_int (g_value_get_boolean (val), TRUE);
162   gst_structure_free (structure);
163
164   /* Tests for flagset deserialisation */
165   s = "foobar,value=0010:ffff";
166   structure = gst_structure_from_string (s, NULL);
167   fail_if (structure == NULL, "Could not get structure from string %s", s);
168   fail_unless ((val = gst_structure_get_value (structure, "value")) != NULL);
169   fail_unless (GST_VALUE_HOLDS_FLAG_SET (val));
170   gst_structure_free (structure);
171
172   /* In the presence of the hex values, the strings don't matter as long as they
173    * have the right form */
174   s = "foobar,value=0010:ffff:+random+other/not-the-other";
175   structure = gst_structure_from_string (s, NULL);
176   fail_if (structure == NULL, "Could not get structure from string %s", s);
177   fail_unless ((val = gst_structure_get_value (structure, "value")) != NULL);
178   fail_unless (GST_VALUE_HOLDS_FLAG_SET (val));
179   gst_structure_free (structure);
180
181   /* Test that a timecode string is deserialised as a string, not a flagset:
182    * https://bugzilla.gnome.org/show_bug.cgi?id=779755 */
183   s = "foobar,timecode=00:01:00:00";
184   structure = gst_structure_from_string (s, NULL);
185   fail_if (structure == NULL, "Could not get structure from string %s", s);
186   fail_unless ((val = gst_structure_get_value (structure, "timecode")) != NULL);
187   fail_unless (G_VALUE_HOLDS_STRING (val));
188   gst_structure_free (structure);
189
190   s = "0.10:decoder-video/mpeg, abc=(boolean)false";
191   ASSERT_CRITICAL (structure = gst_structure_from_string (s, NULL));
192   fail_unless (structure == NULL, "Could not get structure from string %s", s);
193
194   /* make sure we bail out correctly in case of an error or if parsing fails */
195   s = "***foo***, abc=(boolean)false";
196   structure = gst_structure_from_string (s, NULL);
197   fail_unless (structure == NULL);
198
199   /* assert that we get a warning if the structure wasn't entirely consumed, but
200    * we didn't provide an end pointer */
201   s = "foo/bar; other random data";
202   ASSERT_WARNING (structure = gst_structure_from_string (s, NULL));
203   fail_if (structure == NULL, "Could not get structure from string %s", s);
204   gst_structure_free (structure);
205
206   /* make sure we handle \ as last character in various things, run with valgrind */
207   s = "foo,test=\"foobar\\";
208   structure = gst_structure_from_string (s, NULL);
209   fail_unless (structure == NULL);
210   s = "\\";
211   structure = gst_structure_from_string (s, NULL);
212   fail_unless (structure == NULL);
213   s = "foobar,test\\";
214   structure = gst_structure_from_string (s, NULL);
215   fail_unless (structure == NULL);
216   s = "foobar,test=(string)foo\\";
217   structure = gst_structure_from_string (s, NULL);
218   fail_unless (structure == NULL);
219 }
220
221 GST_END_TEST;
222
223
224 GST_START_TEST (test_to_string)
225 {
226   GstStructure *st1;
227
228   ASSERT_CRITICAL (st1 = gst_structure_new_empty ("Foo\nwith-newline"));
229   fail_unless (st1 == NULL);
230
231   ASSERT_CRITICAL (st1 = gst_structure_new_empty ("Foo with whitespace"));
232   fail_unless (st1 == NULL);
233   ASSERT_CRITICAL (st1 = gst_structure_new_empty ("1st"));
234   fail_unless (st1 == NULL);
235 }
236
237 GST_END_TEST;
238
239
240 GST_START_TEST (test_to_from_string)
241 {
242   GstStructure *st1, *st2;
243   gchar *str;
244
245   /* test escaping/unescaping */
246   st1 = gst_structure_new ("FooBar-123/0_1", "num", G_TYPE_INT, 9173,
247       "string", G_TYPE_STRING, "Something Like Face/Off", NULL);
248   str = gst_structure_to_string (st1);
249   st2 = gst_structure_from_string (str, NULL);
250   g_free (str);
251
252   fail_unless (st2 != NULL);
253   fail_unless (gst_structure_is_equal (st1, st2),
254       "Structures did not match:\n\tStructure 1: %" GST_PTR_FORMAT
255       "\n\tStructure 2: %" GST_PTR_FORMAT "\n", st1, st2);
256
257   gst_structure_free (st1);
258   gst_structure_free (st2);
259
260   /* Test NULL strings */
261   st1 = gst_structure_new ("test", "mynullstr", G_TYPE_STRING, NULL, NULL);
262   fail_unless (st1 != NULL);
263   str = gst_structure_to_string (st1);
264   fail_unless (strcmp (str, "test, mynullstr=(string)NULL;") == 0,
265       "Failed to serialize to right string: %s", str);
266
267   st2 = gst_structure_from_string (str, NULL);
268   fail_unless (st2 != NULL);
269   g_free (str);
270
271   fail_unless (gst_structure_is_equal (st1, st2),
272       "Structures did not match:\n\tStructure 1: %" GST_PTR_FORMAT
273       "\n\tStructure 2: %" GST_PTR_FORMAT "\n", st1, st2);
274
275   gst_structure_free (st1);
276   gst_structure_free (st2);
277
278   /* pointers are serialized but not deserialized */
279   st1 = gst_structure_new ("test", "ptr", G_TYPE_POINTER, 0xdeadbeef, NULL);
280   str = gst_structure_to_string (st1);
281   /* The way pointers are serialized may be plateform specific so just check
282    * if it contains the address */
283   fail_unless (g_strrstr (str, "deadbeef") || g_strrstr (str, "DEADBEEF"),
284       "Failed to serialize to right string: %s", str);
285
286   st2 = gst_structure_from_string (str, NULL);
287   fail_unless (!st2);
288
289   gst_structure_free (st1);
290   g_free (str);
291 }
292
293 GST_END_TEST;
294
295 /* Added to make sure taglists are properly serialized/deserialized after bug
296  * https://bugzilla.gnome.org/show_bug.cgi?id=733131 */
297 GST_START_TEST (test_to_from_string_tag_event)
298 {
299   GstEvent *tagevent;
300   GstTagList *taglist;
301   GstStructure *st1, *st2;
302   gchar *str;
303
304   /* empty taglist */
305   taglist = gst_tag_list_new_empty ();
306   tagevent = gst_event_new_tag (taglist);
307
308   st1 = (GstStructure *) gst_event_get_structure (tagevent);
309   str = gst_structure_to_string (st1);
310   fail_unless (str != NULL);
311
312   st2 = gst_structure_new_from_string (str);
313   fail_unless (st2 != NULL);
314   fail_unless (gst_structure_is_equal (st1, st2));
315   gst_event_unref (tagevent);
316   gst_structure_free (st2);
317   g_free (str);
318
319   /* taglist with data */
320   taglist = gst_tag_list_new ("title", "TEST TITLE", NULL);
321   tagevent = gst_event_new_tag (taglist);
322
323   st1 = (GstStructure *) gst_event_get_structure (tagevent);
324   str = gst_structure_to_string (st1);
325   fail_unless (str != NULL);
326
327   st2 = gst_structure_new_from_string (str);
328   fail_unless (st2 != NULL);
329   fail_unless (gst_structure_is_equal (st1, st2));
330   gst_event_unref (tagevent);
331   gst_structure_free (st2);
332   g_free (str);
333 }
334
335 GST_END_TEST;
336
337 GST_START_TEST (test_complete_structure)
338 {
339   GstStructure *structure;
340   const gchar *s;
341
342   s = "GstEventSeek, rate=(double)1, format=(GstFormat)GST_FORMAT_TIME, flags=(GstSeekFlags)GST_SEEK_FLAG_NONE, start_type=(GstSeekType)GST_SEEK_TYPE_SET, start=(gint64)1000000000, stop_type=(GstSeekType)GST_SEEK_TYPE_NONE, stop=(gint64)0";
343   structure = gst_structure_from_string (s, NULL);
344   fail_if (structure == NULL, "Could not get structure from string %s", s);
345   /* FIXME: TODO: add checks for correct serialization of members ? */
346   gst_structure_free (structure);
347 }
348
349 GST_END_TEST;
350
351 GST_START_TEST (test_string_properties)
352 {
353   GstStructure *st1, *st2;
354   gchar *str;
355
356   /* test escaping/unescaping */
357   st1 = gst_structure_new ("RandomStructure", "prop1", G_TYPE_STRING, "foo",
358       "prop2", G_TYPE_STRING, "", "prop3", G_TYPE_STRING, NULL,
359       "prop4", G_TYPE_STRING, "NULL", NULL);
360   str = gst_structure_to_string (st1);
361   st2 = gst_structure_from_string (str, NULL);
362   g_free (str);
363
364   fail_unless (st2 != NULL);
365   fail_unless (gst_structure_is_equal (st1, st2),
366       "Structures did not match:\n\tStructure 1: %" GST_PTR_FORMAT
367       "\n\tStructure 2: %" GST_PTR_FORMAT "\n", st1, st2);
368
369   gst_structure_free (st1);
370   gst_structure_free (st2);
371 }
372
373 GST_END_TEST;
374
375 GST_START_TEST (test_structure_new)
376 {
377   GstStructure *s;
378   GError *e;
379   GQuark domain;
380   gboolean bool;
381   gint num, den;
382   GstClockTime clocktime;
383   guint64 uint64;
384
385   s = gst_structure_new ("name",
386       "key", G_TYPE_STRING, "value",
387       "bool", G_TYPE_BOOLEAN, TRUE,
388       "fraction", GST_TYPE_FRACTION, 1, 5,
389       "clocktime", GST_TYPE_CLOCK_TIME, GST_CLOCK_TIME_NONE,
390       "uint64", G_TYPE_UINT64, (guint64) 1234, NULL);
391
392   fail_unless (gst_structure_get_field_type (s, "unknown") == G_TYPE_INVALID);
393   /* test setting a different name */
394   gst_structure_set_name (s, "newname");
395   fail_unless (strcmp (gst_structure_get_string (s, "key"), "value") == 0);
396   fail_unless (gst_structure_has_field (s, "key"));
397   fail_unless_equals_int (gst_structure_n_fields (s), 5);
398   /* test removing a field */
399   gst_structure_remove_field (s, "key");
400   fail_if (gst_structure_get_string (s, "key"));
401   fail_if (gst_structure_has_field (s, "key"));
402   fail_unless_equals_int (gst_structure_n_fields (s), 4);
403
404   fail_unless (gst_structure_get_boolean (s, "bool", &bool));
405   fail_unless (bool);
406
407   fail_unless (gst_structure_get_fraction (s, "fraction", &num, &den));
408   fail_unless_equals_int (num, 1);
409   fail_unless_equals_int (den, 5);
410
411   fail_unless (gst_structure_get_clock_time (s, "clocktime", &clocktime));
412   fail_unless_equals_uint64 (clocktime, GST_CLOCK_TIME_NONE);
413
414   fail_unless (gst_structure_get_uint64 (s, "uint64", &uint64));
415   fail_unless_equals_uint64 (uint64, 1234);
416
417   gst_structure_free (s);
418
419   domain = g_quark_from_static_string ("test");
420   e = g_error_new (domain, 0, "a test error");
421   s = gst_structure_new ("name", "key", G_TYPE_ERROR, e, NULL);
422   g_error_free (e);
423   gst_structure_free (s);
424
425   ASSERT_CRITICAL (gst_structure_free (gst_structure_new_empty
426           ("0.10:decoder-video/mpeg")));
427
428   /* make sure we bail out correctly in case of an error or if parsing fails */
429   ASSERT_CRITICAL (s = gst_structure_new ("^joo\nba\ndoo^",
430           "abc", G_TYPE_BOOLEAN, FALSE, NULL));
431   fail_unless (s == NULL);
432 }
433
434 GST_END_TEST;
435
436 GST_START_TEST (test_fixate)
437 {
438   GstStructure *s;
439
440   s = gst_structure_new ("name",
441       "int", G_TYPE_INT, 5,
442       "intrange", GST_TYPE_INT_RANGE, 5, 10,
443       "intrange2", GST_TYPE_INT_RANGE, 5, 10, NULL);
444
445   fail_if (gst_structure_fixate_field_nearest_int (s, "int", 5));
446   fail_unless (gst_structure_fixate_field_nearest_int (s, "intrange", 5));
447   fail_if (gst_structure_fixate_field_nearest_int (s, "intrange", 5));
448   fail_unless (gst_structure_fixate_field_nearest_int (s, "intrange2", 15));
449   fail_if (gst_structure_fixate_field_nearest_int (s, "intrange2", 15));
450   gst_structure_free (s);
451 }
452
453 GST_END_TEST;
454
455 GST_START_TEST (test_fixate_frac_list)
456 {
457   GstStructure *s, *s2;
458   GValue list = { 0 };
459   GValue frac = { 0 };
460   gchar *str;
461   gint num, denom;
462
463   g_value_init (&list, GST_TYPE_LIST);
464   g_value_init (&frac, GST_TYPE_FRACTION);
465
466   gst_value_set_fraction (&frac, 30, 1);
467   gst_value_list_append_value (&list, &frac);
468   gst_value_set_fraction (&frac, 15, 1);
469   gst_value_list_append_value (&list, &frac);
470   gst_value_set_fraction (&frac, 10, 1);
471   gst_value_list_append_value (&list, &frac);
472
473   s = gst_structure_new_empty ("name");
474   gst_structure_set_value (s, "frac", &list);
475   g_value_unset (&frac);
476   g_value_unset (&list);
477
478   str = gst_structure_to_string (s);
479   GST_DEBUG ("list %s", str);
480   g_free (str);
481
482   /* take copy */
483   s2 = gst_structure_copy (s);
484
485   /* fixate to the nearest fraction, this should give 15/1 */
486   fail_unless (gst_structure_fixate_field_nearest_fraction (s, "frac", 14, 1));
487
488   fail_unless (gst_structure_get_fraction (s, "frac", &num, &denom));
489   fail_unless (num == 15);
490   fail_unless (denom == 1);
491
492   gst_structure_free (s);
493   s = s2;
494
495   /* fixate to the nearest fraction, this should give 30/1 */
496   fail_unless (gst_structure_fixate_field_nearest_fraction (s, "frac", G_MAXINT,
497           1));
498
499   fail_unless (gst_structure_get_fraction (s, "frac", &num, &denom));
500   fail_unless (num == 30);
501   fail_unless (denom == 1);
502   gst_structure_free (s);
503 }
504
505 GST_END_TEST;
506
507 GST_START_TEST (test_is_subset_equal_array_list)
508 {
509   GstStructure *s1, *s2;
510
511   s1 = gst_structure_from_string ("test/test, channels=(int){ 1, 2 }", NULL);
512   fail_if (s1 == NULL);
513   s2 = gst_structure_from_string ("test/test, channels=(int)[ 1, 2 ]", NULL);
514   fail_if (s2 == NULL);
515
516   fail_unless (gst_structure_is_subset (s1, s2));
517
518   gst_structure_free (s1);
519   gst_structure_free (s2);
520 }
521
522 GST_END_TEST;
523
524 GST_START_TEST (test_is_subset_different_name)
525 {
526   GstStructure *s1, *s2;
527
528   s1 = gst_structure_from_string ("test/test, channels=(int)1", NULL);
529   fail_if (s1 == NULL);
530   s2 = gst_structure_from_string ("test/baz, channels=(int)1", NULL);
531   fail_if (s2 == NULL);
532
533   fail_unless (!gst_structure_is_subset (s1, s2));
534
535   gst_structure_free (s1);
536   gst_structure_free (s2);
537 }
538
539 GST_END_TEST;
540
541 GST_START_TEST (test_is_subset_superset_missing_fields)
542 {
543   GstStructure *s1, *s2;
544
545   /* a missing field is equivalent to any value */
546   s1 = gst_structure_from_string ("test/test, channels=(int)1, rate=(int)1",
547       NULL);
548   fail_if (s1 == NULL);
549   s2 = gst_structure_from_string ("test/test, channels=(int)1", NULL);
550   fail_if (s2 == NULL);
551
552   fail_unless (gst_structure_is_subset (s1, s2));
553
554   gst_structure_free (s1);
555   gst_structure_free (s2);
556 }
557
558 GST_END_TEST;
559
560 GST_START_TEST (test_is_subset_superset_extra_fields)
561 {
562   GstStructure *s1, *s2;
563
564   /* a missing field is equivalent to any value */
565   s1 = gst_structure_from_string ("test/test, channels=(int)1", NULL);
566   fail_if (s1 == NULL);
567   s2 = gst_structure_from_string ("test/test, channels=(int)1, rate=(int)1",
568       NULL);
569   fail_if (s2 == NULL);
570
571   fail_unless (!gst_structure_is_subset (s1, s2));
572
573   gst_structure_free (s1);
574   gst_structure_free (s2);
575 }
576
577 GST_END_TEST;
578
579 GST_START_TEST (test_is_subset_superset_extra_values)
580 {
581   GstStructure *s1, *s2;
582
583   s1 = gst_structure_from_string ("test/test, channels=(int)1", NULL);
584   fail_if (s1 == NULL);
585   s2 = gst_structure_from_string ("test/test, channels=(int)[ 1, 2 ]", NULL);
586   fail_if (s2 == NULL);
587
588   fail_unless (gst_structure_is_subset (s1, s2));
589
590   gst_structure_free (s1);
591   gst_structure_free (s2);
592 }
593
594 GST_END_TEST;
595
596
597 GST_START_TEST (test_structure_nested)
598 {
599   GstStructure *sp, *sc1, *sc2;
600   gchar *str;
601
602   sc1 = gst_structure_new ("Camera",
603       "XResolution", G_TYPE_INT, 72, "YResolution", G_TYPE_INT, 73, NULL);
604   fail_unless (sc1 != NULL);
605
606   sc2 = gst_structure_new ("Image-Data",
607       "Orientation", G_TYPE_STRING, "top-left",
608       "Comment", G_TYPE_STRING, "super photo", NULL);
609   fail_unless (sc2 != NULL);
610
611   sp = gst_structure_new ("Exif", "Camera", GST_TYPE_STRUCTURE, sc1,
612       "Image Data", GST_TYPE_STRUCTURE, sc2, NULL);
613   fail_unless (sp != NULL);
614
615   fail_unless (gst_structure_n_fields (sp) == 2);
616
617   fail_unless (gst_structure_has_field_typed (sp, "Camera",
618           GST_TYPE_STRUCTURE));
619
620   str = gst_structure_to_string (sp);
621   fail_unless (str != NULL);
622
623   GST_DEBUG ("serialized to '%s'", str);
624
625   fail_unless (g_str_equal (str,
626           "Exif"
627           ", Camera=(structure)\"Camera\\,\\ XResolution\\=\\(int\\)72\\,\\ YResolution\\=\\(int\\)73\\;\""
628           ", Image Data=(structure)\"Image-Data\\,\\ Orientation\\=\\(string\\)top-left\\,\\ Comment\\=\\(string\\)\\\"super\\\\\\ photo\\\"\\;\";"));
629
630   g_free (str);
631   str = NULL;
632
633   gst_structure_free (sc1);
634   gst_structure_free (sc2);
635   gst_structure_free (sp);
636 }
637
638 GST_END_TEST;
639
640 GST_START_TEST (test_structure_nested_from_and_to_string)
641 {
642   GstStructure *s;
643   const gchar *str1;
644   gchar *str2, *end = NULL;
645
646   str1 = "main"
647       ", main-sub1=(structure)\"type-b\\,\\ machine-type\\=\\(int\\)0\\;\""
648       ", main-sub2=(structure)\"type-a\\,\\ plugin-filename\\=\\(string\\)\\\"/home/user/lib/lib\\\\\\ with\\\\\\ spaces.dll\\\"\\,\\ machine-type\\=\\(int\\)1\\;\""
649       ", main-sub3=(structure)\"type-b\\,\\ plugin-filename\\=\\(string\\)/home/user/lib/lib_no_spaces.so\\,\\ machine-type\\=\\(int\\)1\\;\""
650       ";";
651
652   s = gst_structure_from_string (str1, &end);
653   fail_unless (s != NULL);
654
655   GST_DEBUG ("not parsed part : %s", end);
656   fail_unless (*end == '\0');
657
658   fail_unless (gst_structure_n_fields (s) == 3);
659
660   fail_unless (gst_structure_has_field_typed (s, "main-sub1",
661           GST_TYPE_STRUCTURE));
662
663   str2 = gst_structure_to_string (s);
664   fail_unless (str2 != NULL);
665
666   fail_unless (g_str_equal (str1, str2));
667
668   g_free (str2);
669
670   gst_structure_free (s);
671 }
672
673 GST_END_TEST;
674
675 GST_START_TEST (test_vararg_getters)
676 {
677   GstStructure *s;
678   GstBuffer *buf, *buf2;
679   gboolean ret;
680   GstCaps *caps, *caps2;
681   GstMapInfo info;
682   gdouble d;
683   gint64 i64;
684   gchar *c;
685   gint i, num, denom;
686   guint8 *data;
687
688   buf = gst_buffer_new_and_alloc (3);
689
690   fail_unless (gst_buffer_map (buf, &info, GST_MAP_WRITE));
691   data = info.data;
692   data[0] = 0xf0;
693   data[1] = 0x66;
694   data[2] = 0x0d;
695   gst_buffer_unmap (buf, &info);
696
697   caps = gst_caps_new_empty_simple ("video/x-foo");
698
699   s = gst_structure_new ("test", "int", G_TYPE_INT, 12345678, "string",
700       G_TYPE_STRING, "Hello World!", "buf", GST_TYPE_BUFFER, buf, "caps",
701       GST_TYPE_CAPS, caps, "int64", G_TYPE_INT64, G_GINT64_CONSTANT (-99),
702       "double", G_TYPE_DOUBLE, G_MAXDOUBLE, "frag", GST_TYPE_FRACTION, 39, 14,
703       NULL);
704
705   /* first the plain one */
706   ret = gst_structure_get (s, "double", G_TYPE_DOUBLE, &d, "string",
707       G_TYPE_STRING, &c, "caps", GST_TYPE_CAPS, &caps2, "buf",
708       GST_TYPE_BUFFER, &buf2, "frag", GST_TYPE_FRACTION, &num, &denom, "int",
709       G_TYPE_INT, &i, "int64", G_TYPE_INT64, &i64, NULL);
710
711   fail_unless (ret);
712   fail_unless_equals_string (c, "Hello World!");
713   fail_unless_equals_int (i, 12345678);
714   fail_unless_equals_float (d, G_MAXDOUBLE);
715   fail_unless_equals_int (num, 39);
716   fail_unless_equals_int (denom, 14);
717   fail_unless (i64 == -99);
718   fail_unless (caps == caps2);
719   fail_unless (buf == buf2);
720
721   /* expected failures */
722   ASSERT_CRITICAL (gst_structure_get (s, NULL, G_TYPE_INT, &i, NULL));
723   fail_if (gst_structure_get (s, "int", G_TYPE_INT, &i, "double",
724           G_TYPE_FLOAT, &d, NULL));
725   fail_if (gst_structure_get (s, "int", G_TYPE_INT, &i, "dooble",
726           G_TYPE_DOUBLE, &d, NULL));
727
728   g_free (c);
729   c = NULL;
730   gst_caps_unref (caps2);
731   caps2 = NULL;
732   gst_buffer_unref (buf2);
733   buf2 = NULL;
734
735   /* and now the _id variant */
736   ret = gst_structure_id_get (s, g_quark_from_static_string ("double"),
737       G_TYPE_DOUBLE, &d, g_quark_from_static_string ("string"), G_TYPE_STRING,
738       &c, g_quark_from_static_string ("caps"), GST_TYPE_CAPS, &caps2,
739       g_quark_from_static_string ("buf"), GST_TYPE_BUFFER, &buf2,
740       g_quark_from_static_string ("int"), G_TYPE_INT, &i,
741       g_quark_from_static_string ("int64"), G_TYPE_INT64, &i64, NULL);
742
743   fail_unless (ret);
744   fail_unless_equals_string (c, "Hello World!");
745   fail_unless_equals_int (i, 12345678);
746   fail_unless_equals_float (d, G_MAXDOUBLE);
747   fail_unless (i64 == -99);
748   fail_unless (caps == caps2);
749   fail_unless (buf == buf2);
750
751   /* expected failures */
752   ASSERT_CRITICAL (gst_structure_get (s, 0, G_TYPE_INT, &i, NULL));
753   fail_if (gst_structure_id_get (s, g_quark_from_static_string ("int"),
754           G_TYPE_INT, &i, g_quark_from_static_string ("double"), G_TYPE_FLOAT,
755           &d, NULL));
756   fail_if (gst_structure_id_get (s, g_quark_from_static_string ("int"),
757           G_TYPE_INT, &i, g_quark_from_static_string ("dooble"), G_TYPE_DOUBLE,
758           &d, NULL));
759
760   g_free (c);
761   gst_caps_unref (caps2);
762   gst_buffer_unref (buf2);
763
764   /* finally make sure NULL as return location is handled gracefully */
765   ret = gst_structure_get (s, "double", G_TYPE_DOUBLE, NULL, "string",
766       G_TYPE_STRING, NULL, "caps", GST_TYPE_CAPS, NULL, "buf",
767       GST_TYPE_BUFFER, NULL, "int", G_TYPE_INT, &i, "frag", GST_TYPE_FRACTION,
768       NULL, NULL, "int64", G_TYPE_INT64, &i64, NULL);
769
770   ASSERT_WARNING (gst_structure_get (s, "frag", GST_TYPE_FRACTION, NULL,
771           &denom, NULL));
772   ASSERT_WARNING (gst_structure_get (s, "frag", GST_TYPE_FRACTION, &num,
773           NULL, NULL));
774
775   /* clean up */
776   gst_caps_unref (caps);
777   gst_buffer_unref (buf);
778   gst_structure_free (s);
779 }
780
781 GST_END_TEST;
782
783 static gboolean
784 foreach_func (GQuark field_id, const GValue * value, gpointer user_data)
785 {
786   gint *sum = user_data;
787   gint v = 0;
788
789   if (G_VALUE_HOLDS_INT (value))
790     v = g_value_get_int (value);
791   *sum += v;
792
793   return TRUE;
794 }
795
796 GST_START_TEST (test_foreach)
797 {
798   GstStructure *s;
799   gint sum = 0;
800
801   s = gst_structure_new ("foo/bar", "baz", G_TYPE_INT, 1, "bla", G_TYPE_INT, 3,
802       NULL);
803   fail_unless (gst_structure_foreach (s, foreach_func, &sum));
804   fail_unless_equals_int (sum, 4);
805   gst_structure_free (s);
806
807 }
808
809 GST_END_TEST;
810
811 static gboolean
812 map_func (GQuark field_id, GValue * value, gpointer user_data)
813 {
814   if (G_VALUE_HOLDS_INT (value))
815     g_value_set_int (value, 123);
816
817   return TRUE;
818 }
819
820 GST_START_TEST (test_map_in_place)
821 {
822   GstStructure *s, *s2;
823
824   s = gst_structure_new ("foo/bar", "baz", G_TYPE_INT, 1, "bla", G_TYPE_INT, 3,
825       NULL);
826   s2 = gst_structure_new ("foo/bar", "baz", G_TYPE_INT, 123, "bla", G_TYPE_INT,
827       123, NULL);
828   fail_unless (gst_structure_map_in_place (s, map_func, NULL));
829   fail_unless (gst_structure_is_equal (s, s2));
830   gst_structure_free (s);
831   gst_structure_free (s2);
832
833 }
834
835 GST_END_TEST;
836
837 static gboolean
838 filter_map_func (GQuark field_id, GValue * value, gpointer user_data)
839 {
840   if (strcmp (g_quark_to_string (field_id), "bla") == 0)
841     return FALSE;
842
843   if (G_VALUE_HOLDS_INT (value))
844     g_value_set_int (value, 2);
845
846   return TRUE;
847 }
848
849 GST_START_TEST (test_filter_and_map_in_place)
850 {
851   GstStructure *s, *s2;
852
853   s = gst_structure_new ("foo/bar", "baz", G_TYPE_INT, 1, "bla", G_TYPE_INT, 3,
854       NULL);
855   s2 = gst_structure_new ("foo/bar", "baz", G_TYPE_INT, 2, NULL);
856   gst_structure_filter_and_map_in_place (s, filter_map_func, NULL);
857   fail_unless (gst_structure_is_equal (s, s2));
858   gst_structure_free (s);
859   gst_structure_free (s2);
860 }
861
862 GST_END_TEST;
863
864 GST_START_TEST (test_flagset)
865 {
866   GstStructure *s;
867   GType test_flagset_type;
868   guint test_flags =
869       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SKIP | GST_SEEK_FLAG_SNAP_AFTER;
870   guint test_mask = GST_FLAG_SET_MASK_EXACT;
871   guint out_flags, out_mask;
872
873   test_flagset_type = gst_flagset_register (GST_TYPE_SEEK_FLAGS);
874   fail_unless (g_type_is_a (test_flagset_type, GST_TYPE_FLAG_SET));
875
876   /* Check that we can retrieve a non-standard flagset from the structure */
877   s = gst_structure_new ("test-struct", "test-flagset", test_flagset_type,
878       test_flags, test_mask, NULL);
879   fail_unless (gst_structure_get_flagset (s, "test-flagset", &out_flags,
880           &out_mask));
881
882   fail_unless (out_flags == test_flags);
883   fail_unless (out_mask == test_mask);
884   gst_structure_free (s);
885 }
886
887 GST_END_TEST;
888
889 static Suite *
890 gst_structure_suite (void)
891 {
892   Suite *s = suite_create ("GstStructure");
893   TCase *tc_chain = tcase_create ("general");
894
895   suite_add_tcase (s, tc_chain);
896   tcase_add_test (tc_chain, test_from_string_int);
897   tcase_add_test (tc_chain, test_from_string_uint);
898   tcase_add_test (tc_chain, test_from_string);
899   tcase_add_test (tc_chain, test_to_string);
900   tcase_add_test (tc_chain, test_to_from_string);
901   tcase_add_test (tc_chain, test_to_from_string_tag_event);
902   tcase_add_test (tc_chain, test_string_properties);
903   tcase_add_test (tc_chain, test_complete_structure);
904   tcase_add_test (tc_chain, test_structure_new);
905   tcase_add_test (tc_chain, test_fixate);
906   tcase_add_test (tc_chain, test_fixate_frac_list);
907   tcase_add_test (tc_chain, test_is_subset_equal_array_list);
908   tcase_add_test (tc_chain, test_is_subset_different_name);
909   tcase_add_test (tc_chain, test_is_subset_superset_missing_fields);
910   tcase_add_test (tc_chain, test_is_subset_superset_extra_fields);
911   tcase_add_test (tc_chain, test_is_subset_superset_extra_values);
912   tcase_add_test (tc_chain, test_structure_nested);
913   tcase_add_test (tc_chain, test_structure_nested_from_and_to_string);
914   tcase_add_test (tc_chain, test_vararg_getters);
915   tcase_add_test (tc_chain, test_foreach);
916   tcase_add_test (tc_chain, test_map_in_place);
917   tcase_add_test (tc_chain, test_filter_and_map_in_place);
918   tcase_add_test (tc_chain, test_flagset);
919   return s;
920 }
921
922 GST_CHECK_MAIN (gst_structure);