tests: fix some leaks in new flagset checks
[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
22
23 #include <gst/gststructure.h>
24 #include <gst/check/gstcheck.h>
25
26
27 GST_START_TEST (test_from_string_int)
28 {
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",
37     /* result from
38      * gst-launch ... ! "video/x-raw, red_mask=(int)0xFF000000" ! ... */
39     "video/x-raw,\\ red_mask=(int)0xFF000000",
40   };
41   gint results[] = {
42     123456,
43     -123456,
44     0xFFFF,
45     0xFFFF,
46     0x7FFFFFFF,
47     (gint) 0x80000000,
48     (gint) 0xFF000000,
49     (gint) 0xFF000000,
50   };
51   GstStructure *structure;
52   int i;
53
54   for (i = 0; i < G_N_ELEMENTS (strings); ++i) {
55     const char *s;
56     const gchar *name;
57     gint value;
58
59     s = strings[i];
60
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);
68
69     /* cleanup */
70     gst_structure_free (structure);
71   }
72 }
73
74 GST_END_TEST;
75
76 GST_START_TEST (test_from_string_uint)
77 {
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"
85   };
86   guint results[] = {
87     123456,
88     0xFFFF,
89     0xFFFF,
90     0x7FFFFFFF,
91     0x80000000,
92     0xFF000000,
93   };
94   GstStructure *structure;
95   int i;
96
97   for (i = 0; i < G_N_ELEMENTS (strings); ++i) {
98     const char *s;
99     const gchar *name;
100     guint value;
101
102     s = strings[i];
103
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);
111
112     /* cleanup */
113     gst_structure_free (structure);
114   }
115 }
116
117 GST_END_TEST;
118
119 /* Test type conversions from string */
120 GST_START_TEST (test_from_string)
121 {
122   GstStructure *structure;
123   const gchar *s;
124   const GValue *val;
125
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);
132
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);
139
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);
146
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);
153
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);
161
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);
165
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);
170
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);
177
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);
182   s = "\\";
183   structure = gst_structure_from_string (s, NULL);
184   fail_unless (structure == NULL);
185   s = "foobar,test\\";
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);
191 }
192
193 GST_END_TEST;
194
195
196 GST_START_TEST (test_to_string)
197 {
198   GstStructure *st1;
199
200   ASSERT_CRITICAL (st1 = gst_structure_new_empty ("Foo\nwith-newline"));
201   fail_unless (st1 == NULL);
202
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);
207 }
208
209 GST_END_TEST;
210
211
212 GST_START_TEST (test_to_from_string)
213 {
214   GstCaps *caps1, *caps2;
215   GstStructure *st1, *st2;
216   gchar *str, *res1, *res2;
217
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);
223   g_free (str);
224
225   fail_unless (st2 != NULL);
226
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",
236       res1, res2);
237   gst_caps_unref (caps1);
238   gst_caps_unref (caps2);
239   g_free (res1);
240   g_free (res2);
241 }
242
243 GST_END_TEST;
244
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)
248 {
249   GstEvent *tagevent;
250   GstTagList *taglist;
251   GstStructure *st1, *st2;
252   gchar *str;
253
254   /* empty taglist */
255   taglist = gst_tag_list_new_empty ();
256   tagevent = gst_event_new_tag (taglist);
257
258   st1 = (GstStructure *) gst_event_get_structure (tagevent);
259   str = gst_structure_to_string (st1);
260   fail_unless (str != NULL);
261
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);
267   g_free (str);
268
269   /* taglist with data */
270   taglist = gst_tag_list_new ("title", "TEST TITLE", NULL);
271   tagevent = gst_event_new_tag (taglist);
272
273   st1 = (GstStructure *) gst_event_get_structure (tagevent);
274   str = gst_structure_to_string (st1);
275   fail_unless (str != NULL);
276
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);
282   g_free (str);
283 }
284
285 GST_END_TEST;
286
287 GST_START_TEST (test_complete_structure)
288 {
289   GstStructure *structure;
290   const gchar *s;
291
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);
297 }
298
299 GST_END_TEST;
300
301 GST_START_TEST (test_string_properties)
302 {
303   GstCaps *caps1, *caps2;
304   GstStructure *st1, *st2;
305   gchar *str, *res1, *res2;
306
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);
313   g_free (str);
314
315   fail_unless (st2 != NULL);
316
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",
326       res1, res2);
327   gst_caps_unref (caps1);
328   gst_caps_unref (caps2);
329   g_free (res1);
330   g_free (res2);
331 }
332
333 GST_END_TEST;
334
335 GST_START_TEST (test_structure_new)
336 {
337   GstStructure *s;
338   GError *e;
339   GQuark domain;
340   gboolean bool;
341   gint num, den;
342   GstClockTime clocktime;
343   guint64 uint64;
344
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);
351
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);
363
364   fail_unless (gst_structure_get_boolean (s, "bool", &bool));
365   fail_unless (bool);
366
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);
370
371   fail_unless (gst_structure_get_clock_time (s, "clocktime", &clocktime));
372   fail_unless_equals_uint64 (clocktime, GST_CLOCK_TIME_NONE);
373
374   fail_unless (gst_structure_get_uint64 (s, "uint64", &uint64));
375   fail_unless_equals_uint64 (uint64, 1234);
376
377   gst_structure_free (s);
378
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);
382   g_error_free (e);
383   gst_structure_free (s);
384
385   ASSERT_CRITICAL (gst_structure_free (gst_structure_new_empty
386           ("0.10:decoder-video/mpeg")));
387
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);
392 }
393
394 GST_END_TEST;
395
396 GST_START_TEST (test_fixate)
397 {
398   GstStructure *s;
399
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);
404
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);
411 }
412
413 GST_END_TEST;
414
415 GST_START_TEST (test_fixate_frac_list)
416 {
417   GstStructure *s, *s2;
418   GValue list = { 0 };
419   GValue frac = { 0 };
420   gchar *str;
421   gint num, denom;
422
423   g_value_init (&list, GST_TYPE_LIST);
424   g_value_init (&frac, GST_TYPE_FRACTION);
425
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);
432
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);
437
438   str = gst_structure_to_string (s);
439   GST_DEBUG ("list %s", str);
440   g_free (str);
441
442   /* take copy */
443   s2 = gst_structure_copy (s);
444
445   /* fixate to the nearest fraction, this should give 15/1 */
446   fail_unless (gst_structure_fixate_field_nearest_fraction (s, "frac", 14, 1));
447
448   fail_unless (gst_structure_get_fraction (s, "frac", &num, &denom));
449   fail_unless (num == 15);
450   fail_unless (denom == 1);
451
452   gst_structure_free (s);
453   s = s2;
454
455   /* fixate to the nearest fraction, this should give 30/1 */
456   fail_unless (gst_structure_fixate_field_nearest_fraction (s, "frac", G_MAXINT,
457           1));
458
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);
463 }
464
465 GST_END_TEST;
466
467 GST_START_TEST (test_is_subset)
468 {
469   GstStructure *s1, *s2;
470
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);
475
476   fail_unless (gst_structure_is_subset (s1, s2));
477
478   gst_structure_free (s1);
479   gst_structure_free (s2);
480 }
481
482 GST_END_TEST;
483
484
485 GST_START_TEST (test_structure_nested)
486 {
487   GstStructure *sp, *sc1, *sc2;
488   gchar *str;
489
490   sc1 = gst_structure_new ("Camera",
491       "XResolution", G_TYPE_INT, 72, "YResolution", G_TYPE_INT, 73, NULL);
492   fail_unless (sc1 != NULL);
493
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);
498
499   sp = gst_structure_new ("Exif", "Camera", GST_TYPE_STRUCTURE, sc1,
500       "Image Data", GST_TYPE_STRUCTURE, sc2, NULL);
501   fail_unless (sp != NULL);
502
503   fail_unless (gst_structure_n_fields (sp) == 2);
504
505   fail_unless (gst_structure_has_field_typed (sp, "Camera",
506           GST_TYPE_STRUCTURE));
507
508   str = gst_structure_to_string (sp);
509   fail_unless (str != NULL);
510
511   GST_DEBUG ("serialized to '%s'", str);
512
513   fail_unless (g_str_equal (str,
514           "Exif"
515           ", Camera=(structure)\"Camera\\,\\ XResolution\\=\\(int\\)72\\,\\ YResolution\\=\\(int\\)73\\;\""
516           ", Image Data=(structure)\"Image-Data\\,\\ Orientation\\=\\(string\\)top-left\\,\\ Comment\\=\\(string\\)\\\"super\\\\\\ photo\\\"\\;\";"));
517
518   g_free (str);
519   str = NULL;
520
521   gst_structure_free (sc1);
522   gst_structure_free (sc2);
523   gst_structure_free (sp);
524 }
525
526 GST_END_TEST;
527
528 GST_START_TEST (test_structure_nested_from_and_to_string)
529 {
530   GstStructure *s;
531   const gchar *str1;
532   gchar *str2, *end = NULL;
533
534   str1 = "main"
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\\;\""
538       ";";
539
540   s = gst_structure_from_string (str1, &end);
541   fail_unless (s != NULL);
542
543   GST_DEBUG ("not parsed part : %s", end);
544   fail_unless (*end == '\0');
545
546   fail_unless (gst_structure_n_fields (s) == 3);
547
548   fail_unless (gst_structure_has_field_typed (s, "main-sub1",
549           GST_TYPE_STRUCTURE));
550
551   str2 = gst_structure_to_string (s);
552   fail_unless (str2 != NULL);
553
554   fail_unless (g_str_equal (str1, str2));
555
556   g_free (str2);
557
558   gst_structure_free (s);
559 }
560
561 GST_END_TEST;
562
563 GST_START_TEST (test_vararg_getters)
564 {
565   GstStructure *s;
566   GstBuffer *buf, *buf2;
567   gboolean ret;
568   GstCaps *caps, *caps2;
569   GstMapInfo info;
570   gdouble d;
571   gint64 i64;
572   gchar *c;
573   gint i, num, denom;
574   guint8 *data;
575
576   buf = gst_buffer_new_and_alloc (3);
577
578   fail_unless (gst_buffer_map (buf, &info, GST_MAP_WRITE));
579   data = info.data;
580   data[0] = 0xf0;
581   data[1] = 0x66;
582   data[2] = 0x0d;
583   gst_buffer_unmap (buf, &info);
584
585   caps = gst_caps_new_empty_simple ("video/x-foo");
586
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,
591       NULL);
592
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);
598
599   fail_unless (ret);
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);
608
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));
615
616   g_free (c);
617   c = NULL;
618   gst_caps_unref (caps2);
619   caps2 = NULL;
620   gst_buffer_unref (buf2);
621   buf2 = NULL;
622
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);
630
631   fail_unless (ret);
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);
638
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,
643           &d, NULL));
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,
646           &d, NULL));
647
648   g_free (c);
649   gst_caps_unref (caps2);
650   gst_buffer_unref (buf2);
651
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);
657
658   ASSERT_WARNING (gst_structure_get (s, "frag", GST_TYPE_FRACTION, NULL,
659           &denom, NULL));
660   ASSERT_WARNING (gst_structure_get (s, "frag", GST_TYPE_FRACTION, &num,
661           NULL, NULL));
662
663   /* clean up */
664   gst_caps_unref (caps);
665   gst_buffer_unref (buf);
666   gst_structure_free (s);
667 }
668
669 GST_END_TEST;
670
671 static gboolean
672 foreach_func (GQuark field_id, const GValue * value, gpointer user_data)
673 {
674   gint *sum = user_data;
675   gint v = 0;
676
677   if (G_VALUE_HOLDS_INT (value))
678     v = g_value_get_int (value);
679   *sum += v;
680
681   return TRUE;
682 }
683
684 GST_START_TEST (test_foreach)
685 {
686   GstStructure *s;
687   gint sum = 0;
688
689   s = gst_structure_new ("foo/bar", "baz", G_TYPE_INT, 1, "bla", G_TYPE_INT, 3,
690       NULL);
691   fail_unless (gst_structure_foreach (s, foreach_func, &sum));
692   fail_unless_equals_int (sum, 4);
693   gst_structure_free (s);
694
695 }
696
697 GST_END_TEST;
698
699 static gboolean
700 map_func (GQuark field_id, GValue * value, gpointer user_data)
701 {
702   if (G_VALUE_HOLDS_INT (value))
703     g_value_set_int (value, 123);
704
705   return TRUE;
706 }
707
708 GST_START_TEST (test_map_in_place)
709 {
710   GstStructure *s, *s2;
711
712   s = gst_structure_new ("foo/bar", "baz", G_TYPE_INT, 1, "bla", G_TYPE_INT, 3,
713       NULL);
714   s2 = gst_structure_new ("foo/bar", "baz", G_TYPE_INT, 123, "bla", G_TYPE_INT,
715       123, NULL);
716   fail_unless (gst_structure_map_in_place (s, map_func, NULL));
717   fail_unless (gst_structure_is_equal (s, s2));
718   gst_structure_free (s);
719   gst_structure_free (s2);
720
721 }
722
723 GST_END_TEST;
724
725 static gboolean
726 filter_map_func (GQuark field_id, GValue * value, gpointer user_data)
727 {
728   if (strcmp (g_quark_to_string (field_id), "bla") == 0)
729     return FALSE;
730
731   if (G_VALUE_HOLDS_INT (value))
732     g_value_set_int (value, 2);
733
734   return TRUE;
735 }
736
737 GST_START_TEST (test_filter_and_map_in_place)
738 {
739   GstStructure *s, *s2;
740
741   s = gst_structure_new ("foo/bar", "baz", G_TYPE_INT, 1, "bla", G_TYPE_INT, 3,
742       NULL);
743   s2 = gst_structure_new ("foo/bar", "baz", G_TYPE_INT, 2, NULL);
744   gst_structure_filter_and_map_in_place (s, filter_map_func, NULL);
745   fail_unless (gst_structure_is_equal (s, s2));
746   gst_structure_free (s);
747   gst_structure_free (s2);
748 }
749
750 GST_END_TEST;
751
752 GST_START_TEST (test_flagset)
753 {
754   GstStructure *s;
755   GType test_flagset_type;
756   guint test_flags =
757       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SKIP | GST_SEEK_FLAG_SNAP_AFTER;
758   guint test_mask = GST_FLAG_SET_MASK_EXACT;
759   guint out_flags, out_mask;
760
761   test_flagset_type = gst_flagset_register (GST_TYPE_SEEK_FLAGS);
762   fail_unless (g_type_is_a (test_flagset_type, GST_TYPE_FLAG_SET));
763
764   /* Check that we can retrieve a non-standard flagset from the structure */
765   s = gst_structure_new ("test-struct", "test-flagset", test_flagset_type,
766       test_flags, test_mask, NULL);
767   fail_unless (gst_structure_get_flagset (s, "test-flagset", &out_flags,
768           &out_mask));
769
770   fail_unless (out_flags == test_flags);
771   fail_unless (out_mask == test_mask);
772   gst_structure_free (s);
773 }
774
775 GST_END_TEST;
776
777 static Suite *
778 gst_structure_suite (void)
779 {
780   Suite *s = suite_create ("GstStructure");
781   TCase *tc_chain = tcase_create ("general");
782
783   suite_add_tcase (s, tc_chain);
784   tcase_add_test (tc_chain, test_from_string_int);
785   tcase_add_test (tc_chain, test_from_string_uint);
786   tcase_add_test (tc_chain, test_from_string);
787   tcase_add_test (tc_chain, test_to_string);
788   tcase_add_test (tc_chain, test_to_from_string);
789   tcase_add_test (tc_chain, test_to_from_string_tag_event);
790   tcase_add_test (tc_chain, test_string_properties);
791   tcase_add_test (tc_chain, test_complete_structure);
792   tcase_add_test (tc_chain, test_structure_new);
793   tcase_add_test (tc_chain, test_fixate);
794   tcase_add_test (tc_chain, test_fixate_frac_list);
795   tcase_add_test (tc_chain, test_is_subset);
796   tcase_add_test (tc_chain, test_structure_nested);
797   tcase_add_test (tc_chain, test_structure_nested_from_and_to_string);
798   tcase_add_test (tc_chain, test_vararg_getters);
799   tcase_add_test (tc_chain, test_foreach);
800   tcase_add_test (tc_chain, test_map_in_place);
801   tcase_add_test (tc_chain, test_filter_and_map_in_place);
802   tcase_add_test (tc_chain, test_flagset);
803   return s;
804 }
805
806 GST_CHECK_MAIN (gst_structure);