[tests/gvariant] Handle flavored_free(NULL), since flavored_malloc can return NULL
[platform/upstream/glib.git] / glib / tests / gvariant.c
1 /*
2  * Copyright © 2010 Codethink Limited
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the licence, or (at your option) any later version.
8  *
9  * See the included COPYING file for more information.
10  *
11  * Author: Ryan Lortie <desrt@desrt.ca>
12  */
13
14 #include <glib/gvariant-internal.h>
15 #include <string.h>
16 #include <stdlib.h>
17 #include <glib.h>
18
19 #define BASIC "bynqiuxthdsog?"
20 #define N_BASIC (G_N_ELEMENTS (BASIC) - 1)
21
22 #define INVALIDS "cefjklpwz&@^$"
23 #define N_INVALIDS (G_N_ELEMENTS (INVALIDS) - 1)
24
25 /* see comment in gvariant-serialiser.c about this madness.
26  *
27  * we use this to get testing of non-strictly-aligned GVariant instances
28  * on machines that can tolerate it.  it is necessary to support this
29  * because some systems have malloc() that returns non-8-aligned
30  * pointers.  it is necessary to have special support in the tests
31  * because on most machines malloc() is 8-aligned.
32  */
33 #define ALIGN_BITS (sizeof (struct { char a; union {                       \
34                       guint64 x; void *y; gdouble z; } b; }) - 9)
35
36 static gboolean
37 randomly (gdouble prob)
38 {
39   return g_test_rand_double_range (0, 1) < prob;
40 }
41
42 /* corecursion */
43 static GVariantType *
44 append_tuple_type_string (GString *, GString *, gboolean, gint);
45
46 /* append a random GVariantType to a GString
47  * append a description of the type to another GString
48  * return what the type is
49  */
50 static GVariantType *
51 append_type_string (GString  *string,
52                     GString  *description,
53                     gboolean  definite,
54                     gint      depth)
55 {
56   if (!depth-- || randomly (0.3))
57     {
58       gchar b = BASIC[g_test_rand_int_range (0, N_BASIC - definite)];
59       g_string_append_c (string, b);
60       g_string_append_c (description, b);
61
62       switch (b)
63         {
64         case 'b':
65           return g_variant_type_copy (G_VARIANT_TYPE_BOOLEAN);
66         case 'y':
67           return g_variant_type_copy (G_VARIANT_TYPE_BYTE);
68         case 'n':
69           return g_variant_type_copy (G_VARIANT_TYPE_INT16);
70         case 'q':
71           return g_variant_type_copy (G_VARIANT_TYPE_UINT16);
72         case 'i':
73           return g_variant_type_copy (G_VARIANT_TYPE_INT32);
74         case 'u':
75           return g_variant_type_copy (G_VARIANT_TYPE_UINT32);
76         case 'x':
77           return g_variant_type_copy (G_VARIANT_TYPE_INT64);
78         case 't':
79           return g_variant_type_copy (G_VARIANT_TYPE_UINT64);
80         case 'h':
81           return g_variant_type_copy (G_VARIANT_TYPE_HANDLE);
82         case 'd':
83           return g_variant_type_copy (G_VARIANT_TYPE_DOUBLE);
84         case 's':
85           return g_variant_type_copy (G_VARIANT_TYPE_STRING);
86         case 'o':
87           return g_variant_type_copy (G_VARIANT_TYPE_OBJECT_PATH);
88         case 'g':
89           return g_variant_type_copy (G_VARIANT_TYPE_SIGNATURE);
90         case '?':
91           return g_variant_type_copy (G_VARIANT_TYPE_BASIC);
92         default:
93           g_assert_not_reached ();
94         }
95     }
96   else
97     {
98       GVariantType *result;
99
100       switch (g_test_rand_int_range (0, definite ? 5 : 7))
101         {
102         case 0:
103           {
104             GVariantType *element;
105
106             g_string_append_c (string, 'a');
107             g_string_append (description, "a of ");
108             element = append_type_string (string, description,
109                                           definite, depth);
110             result = g_variant_type_new_array (element);
111             g_variant_type_free (element);
112           }
113
114           g_assert (g_variant_type_is_array (result));
115           break;
116
117         case 1:
118           {
119             GVariantType *element;
120
121             g_string_append_c (string, 'm');
122             g_string_append (description, "m of ");
123             element = append_type_string (string, description,
124                                           definite, depth);
125             result = g_variant_type_new_maybe (element);
126             g_variant_type_free (element);
127           }
128
129           g_assert (g_variant_type_is_maybe (result));
130           break;
131
132         case 2:
133           result = append_tuple_type_string (string, description,
134                                              definite, depth);
135
136           g_assert (g_variant_type_is_tuple (result));
137           break;
138
139         case 3:
140           {
141             GVariantType *key, *value;
142
143             g_string_append_c (string, '{');
144             g_string_append (description, "e of [");
145             key = append_type_string (string, description, definite, 0);
146             g_string_append (description, ", ");
147             value = append_type_string (string, description, definite, depth);
148             g_string_append_c (description, ']');
149             g_string_append_c (string, '}');
150             result = g_variant_type_new_dict_entry (key, value);
151             g_variant_type_free (key);
152             g_variant_type_free (value);
153           }
154
155           g_assert (g_variant_type_is_dict_entry (result));
156           break;
157
158         case 4:
159           g_string_append_c (string, 'v');
160           g_string_append_c (description, 'V');
161           result = g_variant_type_copy (G_VARIANT_TYPE_VARIANT);
162           g_assert (g_variant_type_equal (result, G_VARIANT_TYPE_VARIANT));
163           break;
164
165         case 5:
166           g_string_append_c (string, '*');
167           g_string_append_c (description, 'S');
168           result = g_variant_type_copy (G_VARIANT_TYPE_ANY);
169           g_assert (g_variant_type_equal (result, G_VARIANT_TYPE_ANY));
170           break;
171
172         case 6:
173           g_string_append_c (string, 'r');
174           g_string_append_c (description, 'R');
175           result = g_variant_type_copy (G_VARIANT_TYPE_TUPLE);
176           g_assert (g_variant_type_is_tuple (result));
177           break;
178
179         default:
180           g_assert_not_reached ();
181         }
182
183       return result;
184     }
185 }
186
187 static GVariantType *
188 append_tuple_type_string (GString  *string,
189                           GString  *description,
190                           gboolean  definite,
191                           gint      depth)
192 {
193   GVariantType *result, *other_result;
194   GVariantType **types;
195   gint size;
196   gint i;
197
198   g_string_append_c (string, '(');
199   g_string_append (description, "t of [");
200
201   size = g_test_rand_int_range (0, 20);
202   types = g_new (GVariantType *, size + 1);
203
204   for (i = 0; i < size; i++)
205     {
206       types[i] = append_type_string (string, description, definite, depth);
207
208       if (i < size - 1)
209         g_string_append (description, ", ");
210     }
211
212   types[i] = NULL;
213
214   g_string_append_c (description, ']');
215   g_string_append_c (string, ')');
216
217   result = g_variant_type_new_tuple ((gpointer) types, size);
218   other_result = g_variant_type_new_tuple ((gpointer) types, -1);
219   g_assert (g_variant_type_equal (result, other_result));
220   g_variant_type_free (other_result);
221   for (i = 0; i < size; i++)
222     g_variant_type_free (types[i]);
223   g_free (types);
224
225   return result;
226 }
227
228 /* given a valid type string, make it invalid */
229 static gchar *
230 invalid_mutation (const gchar *type_string)
231 {
232   gboolean have_parens, have_braces;
233
234   /* it's valid, so '(' implies ')' and same for '{' and '}' */
235   have_parens = strchr (type_string, '(') != NULL;
236   have_braces = strchr (type_string, '{') != NULL;
237
238   if (have_parens && have_braces && randomly (0.3))
239     {
240       /* swap a paren and a brace */
241       gchar *pp, *bp;
242       gint np, nb;
243       gchar p, b;
244       gchar *new;
245
246       new = g_strdup (type_string);
247
248       if (randomly (0.5))
249         p = '(', b = '{';
250       else
251         p = ')', b = '}';
252
253       np = nb = 0;
254       pp = bp = new - 1;
255
256       /* count number of parens/braces */
257       while ((pp = strchr (pp + 1, p))) np++;
258       while ((bp = strchr (bp + 1, b))) nb++;
259
260       /* randomly pick one of each */
261       np = g_test_rand_int_range (0, np) + 1;
262       nb = g_test_rand_int_range (0, nb) + 1;
263
264       /* find it */
265       pp = bp = new - 1;
266       while (np--) pp = strchr (pp + 1, p);
267       while (nb--) bp = strchr (bp + 1, b);
268
269       /* swap */
270       g_assert (*bp == b && *pp == p);
271       *bp = p;
272       *pp = b;
273
274       return new;
275     }
276
277   if ((have_parens || have_braces) && randomly (0.3))
278     {
279       /* drop a paren/brace */
280       gchar *new;
281       gchar *pp;
282       gint np;
283       gchar p;
284
285       if (have_parens)
286         if (randomly (0.5)) p = '('; else p = ')';
287       else
288         if (randomly (0.5)) p = '{'; else p = '}';
289
290       new = g_strdup (type_string);
291
292       np = 0;
293       pp = new - 1;
294       while ((pp = strchr (pp + 1, p))) np++;
295       np = g_test_rand_int_range (0, np) + 1;
296       pp = new - 1;
297       while (np--) pp = strchr (pp + 1, p);
298       g_assert (*pp == p);
299
300       while (*pp)
301         {
302           *pp = *(pp + 1);
303           pp++;
304         }
305
306       return new;
307     }
308
309   /* else, perform a random mutation at a random point */
310   {
311     gint length, n;
312     gchar *new;
313     gchar p;
314
315     if (randomly (0.3))
316       {
317         /* insert a paren/brace */
318         if (randomly (0.5))
319           if (randomly (0.5)) p = '('; else p = ')';
320         else
321           if (randomly (0.5)) p = '{'; else p = '}';
322       }
323     else if (randomly (0.5))
324       {
325         /* insert junk */
326         p = INVALIDS[g_test_rand_int_range (0, N_INVALIDS)];
327       }
328     else
329       {
330         /* truncate */
331         p = '\0';
332       }
333
334
335     length = strlen (type_string);
336     new = g_malloc (length + 2);
337     n = g_test_rand_int_range (0, length);
338     memcpy (new, type_string, n);
339     new[n] = p;
340     memcpy (new + n + 1, type_string + n, length - n);
341     new[length + 1] = '\0';
342
343     return new;
344   }
345 }
346
347 /* describe a type using the same language as is generated
348  * while generating the type with append_type_string
349  */
350 static gchar *
351 describe_type (const GVariantType *type)
352 {
353   gchar *result;
354
355   if (g_variant_type_is_container (type))
356     {
357       g_assert (!g_variant_type_is_basic (type));
358
359       if (g_variant_type_is_array (type))
360         {
361           gchar *subtype = describe_type (g_variant_type_element (type));
362           result = g_strdup_printf ("a of %s", subtype);
363           g_free (subtype);
364         }
365       else if (g_variant_type_is_maybe (type))
366         {
367           gchar *subtype = describe_type (g_variant_type_element (type));
368           result = g_strdup_printf ("m of %s", subtype);
369           g_free (subtype);
370         }
371       else if (g_variant_type_is_tuple (type))
372         {
373           if (!g_variant_type_equal (type, G_VARIANT_TYPE_TUPLE))
374             {
375               const GVariantType *sub;
376               GString *string;
377               gint length;
378               gint i;
379
380               string = g_string_new ("t of [");
381
382               length = g_variant_type_n_items (type);
383               sub = g_variant_type_first (type);
384               for (i = 0; i < length; i++)
385                 {
386                   gchar *subtype = describe_type (sub);
387                   g_string_append (string, subtype);
388                   g_free (subtype);
389
390                   if ((sub = g_variant_type_next (sub)))
391                     g_string_append (string, ", ");
392                 }
393               g_assert (sub == NULL);
394               g_string_append_c (string, ']');
395
396               result = g_string_free (string, FALSE);
397             }
398           else
399             result = g_strdup ("R");
400         }
401       else if (g_variant_type_is_dict_entry (type))
402         {
403           gchar *key, *value, *key2, *value2;
404
405           key = describe_type (g_variant_type_key (type));
406           value = describe_type (g_variant_type_value (type));
407           key2 = describe_type (g_variant_type_first (type));
408           value2 = describe_type (
409             g_variant_type_next (g_variant_type_first (type)));
410           g_assert (g_variant_type_next (g_variant_type_next (
411             g_variant_type_first (type))) == NULL);
412           g_assert_cmpstr (key, ==, key2);
413           g_assert_cmpstr (value, ==, value2);
414           result = g_strjoin ("", "e of [", key, ", ", value, "]", NULL);
415           g_free (key2);
416           g_free (value2);
417           g_free (key);
418           g_free (value);
419         }
420       else if (g_variant_type_equal (type, G_VARIANT_TYPE_VARIANT))
421         {
422           result = g_strdup ("V");
423         }
424       else
425         g_assert_not_reached ();
426     }
427   else
428     {
429       if (g_variant_type_is_definite (type))
430         {
431           g_assert (g_variant_type_is_basic (type));
432
433           if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN))
434             result = g_strdup ("b");
435           else if (g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
436             result = g_strdup ("y");
437           else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT16))
438             result = g_strdup ("n");
439           else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT16))
440             result = g_strdup ("q");
441           else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32))
442             result = g_strdup ("i");
443           else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT32))
444             result = g_strdup ("u");
445           else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT64))
446             result = g_strdup ("x");
447           else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT64))
448             result = g_strdup ("t");
449           else if (g_variant_type_equal (type, G_VARIANT_TYPE_HANDLE))
450             result = g_strdup ("h");
451           else if (g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
452             result = g_strdup ("d");
453           else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING))
454             result = g_strdup ("s");
455           else if (g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH))
456             result = g_strdup ("o");
457           else if (g_variant_type_equal (type, G_VARIANT_TYPE_SIGNATURE))
458             result = g_strdup ("g");
459           else
460             g_assert_not_reached ();
461         }
462       else
463         {
464           if (g_variant_type_equal (type, G_VARIANT_TYPE_ANY))
465             {
466               result = g_strdup ("S");
467             }
468           else if (g_variant_type_equal (type, G_VARIANT_TYPE_BASIC))
469             {
470               result = g_strdup ("?");
471             }
472           else
473             g_assert_not_reached ();
474         }
475     }
476
477   return result;
478 }
479
480 /* given a type string, replace one of the indefinite type characters in
481  * it with a matching type (possibly the same type).
482  */
483 static gchar *
484 generate_subtype (const gchar *type_string)
485 {
486   GVariantType *replacement;
487   GString *result, *junk;
488   gint length, n = 0, l;
489
490   result = g_string_new (NULL);
491   junk = g_string_new (NULL);
492
493   /* count the number of indefinite type characters */
494   for (length = 0; type_string[length]; length++)
495     n += type_string[length] == 'r' ||
496          type_string[length] == '?' ||
497          type_string[length] == '*';
498   /* length now is strlen (type_string) */
499
500   /* pick one at random to replace */
501   n = g_test_rand_int_range (0, n) + 1;
502
503   /* find it */
504   l = -1;
505   while (n--) l += strcspn (type_string + l + 1, "r?*") + 1;
506   g_assert (type_string[l] == 'r' ||
507             type_string[l] == '?' ||
508             type_string[l] == '*');
509
510   /* store up to that point in a GString */
511   g_string_append_len (result, type_string, l);
512
513   /* then store the replacement in the GString */
514   if (type_string[l] == 'r')
515     replacement = append_tuple_type_string (result, junk, FALSE, 3);
516
517   else if (type_string[l] == '?')
518     replacement = append_type_string (result, junk, FALSE, 0);
519
520   else if (type_string[l] == '*')
521     replacement = append_type_string (result, junk, FALSE, 3);
522
523   else
524     g_assert_not_reached ();
525
526   /* ensure the replacement has the proper type */
527   g_assert (g_variant_type_is_subtype_of (replacement,
528                                           (gpointer) &type_string[l]));
529
530   /* store the rest from the original type string */
531   g_string_append (result, type_string + l + 1);
532
533   g_variant_type_free (replacement);
534   g_string_free (junk, TRUE);
535
536   return g_string_free (result, FALSE);
537 }
538
539 struct typestack
540 {
541   const GVariantType *type;
542   struct typestack *parent;
543 };
544
545 /* given an indefinite type string, replace one of the indefinite
546  * characters in it with a matching type and ensure that the result is a
547  * subtype of the original.  repeat.
548  */
549 static void
550 subtype_check (const gchar      *type_string,
551                struct typestack *parent_ts)
552 {
553   struct typestack ts, *node;
554   gchar *subtype;
555   gint depth = 0;
556
557   subtype = generate_subtype (type_string);
558
559   ts.type = G_VARIANT_TYPE (subtype);
560   ts.parent = parent_ts;
561
562   for (node = &ts; node; node = node->parent)
563     {
564       /* this type should be a subtype of each parent type */
565       g_assert (g_variant_type_is_subtype_of (ts.type, node->type));
566
567       /* it should only be a supertype when it is exactly equal */
568       g_assert (g_variant_type_is_subtype_of (node->type, ts.type) ==
569                 g_variant_type_equal (ts.type, node->type));
570
571       depth++;
572     }
573
574   if (!g_variant_type_is_definite (ts.type) && depth < 5)
575     {
576       /* the type is still indefinite and we haven't repeated too many
577        * times.  go once more.
578        */
579
580       subtype_check (subtype, &ts);
581     }
582
583   g_free (subtype);
584 }
585
586 static void
587 test_gvarianttype (void)
588 {
589   gint i;
590
591   for (i = 0; i < 2000; i++)
592     {
593       GString *type_string, *description;
594       GVariantType *type, *other_type;
595       const GVariantType *ctype;
596       gchar *invalid;
597       gchar *desc;
598
599       type_string = g_string_new (NULL);
600       description = g_string_new (NULL);
601
602       /* generate a random type, its type string and a description
603        *
604        * exercises type constructor functions and g_variant_type_copy()
605        */
606       type = append_type_string (type_string, description, FALSE, 6);
607
608       /* convert the type string to a type and ensure that it is equal
609        * to the one produced with the type constructor routines
610        */
611       ctype = G_VARIANT_TYPE (type_string->str);
612       g_assert (g_variant_type_equal (ctype, type));
613       g_assert (g_variant_type_is_subtype_of (ctype, type));
614       g_assert (g_variant_type_is_subtype_of (type, ctype));
615
616       /* check if the type is indefinite */
617       if (!g_variant_type_is_definite (type))
618         {
619           struct typestack ts = { type, NULL };
620
621           /* if it is indefinite, then replace one of the indefinite
622            * characters with a matching type and ensure that the result
623            * is a subtype of the original type.  repeat.
624            */
625           subtype_check (type_string->str, &ts);
626         }
627       else
628         /* ensure that no indefinite characters appear */
629         g_assert (strcspn (type_string->str, "r?*") == type_string->len);
630
631
632       /* describe the type.
633        *
634        * exercises the type iterator interface
635        */
636       desc = describe_type (type);
637
638       /* make sure the description matches */
639       g_assert_cmpstr (desc, ==, description->str);
640       g_free (desc);
641
642       /* make an invalid mutation to the type and make sure the type
643        * validation routines catch it */
644       invalid = invalid_mutation (type_string->str);
645       g_assert (g_variant_type_string_is_valid (type_string->str));
646       g_assert (!g_variant_type_string_is_valid (invalid));
647       g_free (invalid);
648
649       /* concatenate another type to the type string and ensure that
650        * the result is recognised as being invalid
651        */
652       other_type = append_type_string (type_string, description, FALSE, 2);
653
654       g_string_free (description, TRUE);
655       g_string_free (type_string, TRUE);
656       g_variant_type_free (other_type);
657       g_variant_type_free (type);
658     }
659 }
660
661 #define ALIGNED(x, y)   (((x + (y - 1)) / y) * y)
662
663 /* do our own calculation of the fixed_size and alignment of a type
664  * using a simple algorithm to make sure the "fancy" one in the
665  * implementation is correct.
666  */
667 static void
668 calculate_type_info (const GVariantType *type,
669                      gsize              *fixed_size,
670                      guint              *alignment)
671 {
672   if (g_variant_type_is_array (type) ||
673       g_variant_type_is_maybe (type))
674     {
675       calculate_type_info (g_variant_type_element (type), NULL, alignment);
676
677       if (fixed_size)
678         *fixed_size = 0;
679     }
680   else if (g_variant_type_is_tuple (type) ||
681            g_variant_type_is_dict_entry (type))
682     {
683       if (g_variant_type_n_items (type))
684         {
685           const GVariantType *sub;
686           gboolean variable;
687           gsize size;
688           guint al;
689
690           variable = FALSE;
691           size = 0;
692           al = 0;
693
694           sub = g_variant_type_first (type);
695           do
696             {
697               gsize this_fs;
698               guint this_al;
699
700               calculate_type_info (sub, &this_fs, &this_al);
701
702               al = MAX (al, this_al);
703
704               if (!this_fs)
705                 {
706                   variable = TRUE;
707                   size = 0;
708                 }
709
710               if (!variable)
711                 {
712                   size = ALIGNED (size, this_al);
713                   size += this_fs;
714                 }
715             }
716           while ((sub = g_variant_type_next (sub)));
717
718           size = ALIGNED (size, al);
719
720           if (alignment)
721             *alignment = al;
722
723           if (fixed_size)
724             *fixed_size = size;
725         }
726       else
727         {
728           if (fixed_size)
729             *fixed_size = 1;
730
731           if (alignment)
732             *alignment = 1;
733         }
734     }
735   else
736     {
737       gint fs, al;
738
739       if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN) ||
740           g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
741         {
742           al = fs = 1;
743         }
744
745       else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT16) ||
746                g_variant_type_equal (type, G_VARIANT_TYPE_UINT16))
747         {
748           al = fs = 2;
749         }
750
751       else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32) ||
752                g_variant_type_equal (type, G_VARIANT_TYPE_UINT32) ||
753                g_variant_type_equal (type, G_VARIANT_TYPE_HANDLE))
754         {
755           al = fs = 4;
756         }
757
758       else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT64) ||
759                g_variant_type_equal (type, G_VARIANT_TYPE_UINT64) ||
760                g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
761         {
762           al = fs = 8;
763         }
764       else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING) ||
765                g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH) ||
766                g_variant_type_equal (type, G_VARIANT_TYPE_SIGNATURE))
767         {
768           al = 1;
769           fs = 0;
770         }
771       else if (g_variant_type_equal (type, G_VARIANT_TYPE_VARIANT))
772         {
773           al = 8;
774           fs = 0;
775         }
776       else
777         g_assert_not_reached ();
778
779       if (fixed_size)
780         *fixed_size = fs;
781
782       if (alignment)
783         *alignment = al;
784     }
785 }
786
787 /* same as the describe_type() function above, but iterates over
788  * typeinfo instead of types.
789  */
790 static gchar *
791 describe_info (GVariantTypeInfo *info)
792 {
793   gchar *result;
794
795   switch (g_variant_type_info_get_type_char (info))
796     {
797     case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
798       {
799         gchar *element;
800
801         element = describe_info (g_variant_type_info_element (info));
802         result = g_strdup_printf ("m of %s", element);
803         g_free (element);
804       }
805       break;
806
807     case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
808       {
809         gchar *element;
810
811         element = describe_info (g_variant_type_info_element (info));
812         result = g_strdup_printf ("a of %s", element);
813         g_free (element);
814       }
815       break;
816
817     case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
818       {
819         const gchar *sep = "";
820         GString *string;
821         gint length;
822         gint i;
823
824         string = g_string_new ("t of [");
825         length = g_variant_type_info_n_members (info);
826
827         for (i = 0; i < length; i++)
828           {
829             const GVariantMemberInfo *minfo;
830             gchar *subtype;
831
832             g_string_append (string, sep);
833             sep = ", ";
834
835             minfo = g_variant_type_info_member_info (info, i);
836             subtype = describe_info (minfo->type_info);
837             g_string_append (string, subtype);
838             g_free (subtype);
839           }
840
841         g_string_append_c (string, ']');
842
843         result = g_string_free (string, FALSE);
844       }
845       break;
846
847     case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
848       {
849         const GVariantMemberInfo *keyinfo, *valueinfo;
850         gchar *key, *value;
851
852         g_assert_cmpint (g_variant_type_info_n_members (info), ==, 2);
853         keyinfo = g_variant_type_info_member_info (info, 0);
854         valueinfo = g_variant_type_info_member_info (info, 1);
855         key = describe_info (keyinfo->type_info);
856         value = describe_info (valueinfo->type_info);
857         result = g_strjoin ("", "e of [", key, ", ", value, "]", NULL);
858         g_free (key);
859         g_free (value);
860       }
861       break;
862
863     case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
864       result = g_strdup ("V");
865       break;
866
867     default:
868       result = g_strdup (g_variant_type_info_get_type_string (info));
869       g_assert_cmpint (strlen (result), ==, 1);
870       break;
871     }
872
873   return result;
874 }
875
876 /* check that the O(1) method of calculating offsets meshes with the
877  * results of simple iteration.
878  */
879 static void
880 check_offsets (GVariantTypeInfo   *info,
881                const GVariantType *type)
882 {
883   gint flavour;
884   gint length;
885
886   length = g_variant_type_info_n_members (info);
887   g_assert_cmpint (length, ==, g_variant_type_n_items (type));
888
889   /* the 'flavour' is the low order bits of the ending point of
890    * variable-size items in the tuple.  this lets us test that the type
891    * info is correct for various starting alignments.
892    */
893   for (flavour = 0; flavour < 8; flavour++)
894     {
895       const GVariantType *subtype;
896       gsize last_offset_index;
897       gsize last_offset;
898       gsize position;
899       gint i;
900
901       subtype = g_variant_type_first (type);
902       last_offset_index = -1;
903       last_offset = 0;
904       position = 0;
905
906       /* go through the tuple, keeping track of our position */
907       for (i = 0; i < length; i++)
908         {
909           gsize fixed_size;
910           guint alignment;
911
912           calculate_type_info (subtype, &fixed_size, &alignment);
913
914           position = ALIGNED (position, alignment);
915
916           /* compare our current aligned position (ie: the start of this
917            * item) to the start offset that would be calculated if we
918            * used the type info
919            */
920           {
921             const GVariantMemberInfo *member;
922             gsize start;
923
924             member = g_variant_type_info_member_info (info, i);
925             g_assert_cmpint (member->i, ==, last_offset_index);
926
927             /* do the calculation using the typeinfo */
928             start = last_offset;
929             start += member->a;
930             start &= member->b;
931             start |= member->c;
932
933             /* did we reach the same spot? */
934             g_assert_cmpint (start, ==, position);
935           }
936
937           if (fixed_size)
938             {
939               /* fixed size.  add that size. */
940               position += fixed_size;
941             }
942           else
943             {
944               /* variable size.  do the flavouring. */
945               while ((position & 0x7) != flavour)
946                 position++;
947
948               /* and store the offset, just like it would be in the
949                * serialised data.
950                */
951               last_offset = position;
952               last_offset_index++;
953             }
954
955           /* next type */
956           subtype = g_variant_type_next (subtype);
957         }
958
959       /* make sure we used up exactly all the types */
960       g_assert (subtype == NULL);
961     }
962 }
963
964 static void
965 test_gvarianttypeinfo (void)
966 {
967   gint i;
968
969   for (i = 0; i < 2000; i++)
970     {
971       GString *type_string, *description;
972       gsize fixed_size1, fixed_size2;
973       guint alignment1, alignment2;
974       GVariantTypeInfo *info;
975       GVariantType *type;
976       gchar *desc;
977
978       type_string = g_string_new (NULL);
979       description = g_string_new (NULL);
980
981       /* random type */
982       type = append_type_string (type_string, description, TRUE, 6);
983
984       /* create a typeinfo for it */
985       info = g_variant_type_info_get (type);
986
987       /* make sure the typeinfo has the right type string */
988       g_assert_cmpstr (g_variant_type_info_get_type_string (info), ==,
989                        type_string->str);
990
991       /* calculate the alignment and fixed size, compare to the
992        * typeinfo's calculations
993        */
994       calculate_type_info (type, &fixed_size1, &alignment1);
995       g_variant_type_info_query (info, &alignment2, &fixed_size2);
996       g_assert_cmpint (fixed_size1, ==, fixed_size2);
997       g_assert_cmpint (alignment1, ==, alignment2 + 1);
998
999       /* test the iteration functions over typeinfo structures by
1000        * "describing" the typeinfo and verifying equality.
1001        */
1002       desc = describe_info (info);
1003       g_assert_cmpstr (desc, ==, description->str);
1004
1005       /* do extra checks for containers */
1006       if (g_variant_type_is_array (type) ||
1007           g_variant_type_is_maybe (type))
1008         {
1009           const GVariantType *element;
1010           gsize efs1, efs2;
1011           guint ea1, ea2;
1012
1013           element = g_variant_type_element (type);
1014           calculate_type_info (element, &efs1, &ea1);
1015           g_variant_type_info_query_element (info, &ea2, &efs2);
1016           g_assert_cmpint (efs1, ==, efs2);
1017           g_assert_cmpint (ea1, ==, ea2 + 1);
1018
1019           g_assert_cmpint (ea1, ==, alignment1);
1020           g_assert_cmpint (0, ==, fixed_size1);
1021         }
1022       else if (g_variant_type_is_tuple (type) ||
1023                g_variant_type_is_dict_entry (type))
1024         {
1025           /* make sure the "magic constants" are working */
1026           check_offsets (info, type);
1027         }
1028
1029       g_string_free (type_string, TRUE);
1030       g_string_free (description, TRUE);
1031       g_variant_type_info_unref (info);
1032       g_variant_type_free (type);
1033       g_free (desc);
1034     }
1035
1036   g_variant_type_info_assert_no_infos ();
1037 }
1038
1039 #define MAX_FIXED_MULTIPLIER    256
1040 #define MAX_INSTANCE_SIZE       1024
1041 #define MAX_ARRAY_CHILDREN      128
1042 #define MAX_TUPLE_CHILDREN      128
1043
1044 /* this function generates a random type such that all characteristics
1045  * that are "interesting" to the serialiser are tested.
1046  *
1047  * this basically means:
1048  *   - test different alignments
1049  *   - test variable sized items and fixed sized items
1050  *   - test different fixed sizes
1051  */
1052 static gchar *
1053 random_type_string (void)
1054 {
1055   const guchar base_types[] = "ynix";
1056   guchar base_type;
1057
1058   base_type = base_types[g_test_rand_int_range (0, 4)];
1059
1060   if (g_test_rand_bit ())
1061     /* construct a fixed-sized type */
1062     {
1063       char type_string[MAX_FIXED_MULTIPLIER];
1064       guint multiplier;
1065       guint i = 0;
1066
1067       multiplier = g_test_rand_int_range (1, sizeof type_string - 1);
1068
1069       type_string[i++] = '(';
1070       while (multiplier--)
1071         type_string[i++] = base_type;
1072       type_string[i++] = ')';
1073
1074       return g_strndup (type_string, i);
1075     }
1076   else
1077     /* construct a variable-sized type */
1078     {
1079       char type_string[2] = { 'a', base_type };
1080
1081       return g_strndup (type_string, 2);
1082     }
1083 }
1084
1085 typedef struct
1086 {
1087   GVariantTypeInfo *type_info;
1088   guint alignment;
1089   gsize size;
1090   gboolean is_fixed_sized;
1091
1092   guint32 seed;
1093
1094 #define INSTANCE_MAGIC    1287582829
1095   guint magic;
1096 } RandomInstance;
1097
1098 static RandomInstance *
1099 random_instance (GVariantTypeInfo *type_info)
1100 {
1101   RandomInstance *instance;
1102
1103   instance = g_slice_new (RandomInstance);
1104
1105   if (type_info == NULL)
1106     {
1107       gchar *str = random_type_string ();
1108       instance->type_info = g_variant_type_info_get (G_VARIANT_TYPE (str));
1109       g_free (str);
1110     }
1111   else
1112     instance->type_info = g_variant_type_info_ref (type_info);
1113
1114   instance->seed = g_test_rand_int ();
1115
1116   g_variant_type_info_query (instance->type_info,
1117                              &instance->alignment,
1118                              &instance->size);
1119
1120   instance->is_fixed_sized = instance->size != 0;
1121
1122   if (!instance->is_fixed_sized)
1123     instance->size = g_test_rand_int_range (0, MAX_INSTANCE_SIZE);
1124
1125   instance->magic = INSTANCE_MAGIC;
1126
1127   return instance;
1128 }
1129
1130 static void
1131 random_instance_free (RandomInstance *instance)
1132 {
1133   g_variant_type_info_unref (instance->type_info);
1134   g_slice_free (RandomInstance, instance);
1135 }
1136
1137 static void
1138 append_instance_size (RandomInstance *instance,
1139                       gsize          *offset)
1140 {
1141   *offset += (-*offset) & instance->alignment;
1142   *offset += instance->size;
1143 }
1144
1145 static void
1146 random_instance_write (RandomInstance *instance,
1147                        guchar         *buffer)
1148 {
1149   GRand *rand;
1150   gint i;
1151
1152   g_assert_cmpint ((gsize) buffer & ALIGN_BITS & instance->alignment, ==, 0);
1153
1154   rand = g_rand_new_with_seed (instance->seed);
1155   for (i = 0; i < instance->size; i++)
1156     buffer[i] = g_rand_int (rand);
1157   g_rand_free (rand);
1158 }
1159
1160 static void
1161 append_instance_data (RandomInstance  *instance,
1162                       guchar         **buffer)
1163 {
1164   while (((gsize) *buffer) & instance->alignment)
1165     *(*buffer)++ = '\0';
1166
1167   random_instance_write (instance, *buffer);
1168   *buffer += instance->size;
1169 }
1170
1171 static gboolean
1172 random_instance_assert (RandomInstance *instance,
1173                         guchar         *buffer,
1174                         gsize           size)
1175 {
1176   GRand *rand;
1177   gint i;
1178
1179   g_assert_cmpint ((gsize) buffer & ALIGN_BITS & instance->alignment, ==, 0);
1180   g_assert_cmpint (size, ==, instance->size);
1181
1182   rand = g_rand_new_with_seed (instance->seed);
1183   for (i = 0; i < instance->size; i++)
1184     {
1185       guchar byte = g_rand_int (rand);
1186
1187       g_assert (buffer[i] == byte);
1188     }
1189   g_rand_free (rand);
1190
1191   return i == instance->size;
1192 }
1193
1194 static gboolean
1195 random_instance_check (RandomInstance *instance,
1196                        guchar         *buffer,
1197                        gsize           size)
1198 {
1199   GRand *rand;
1200   gint i;
1201
1202   g_assert_cmpint ((gsize) buffer & ALIGN_BITS & instance->alignment, ==, 0);
1203
1204   if (size != instance->size)
1205     return FALSE;
1206
1207   rand = g_rand_new_with_seed (instance->seed);
1208   for (i = 0; i < instance->size; i++)
1209     if (buffer[i] != (guchar) g_rand_int (rand))
1210       break;
1211   g_rand_free (rand);
1212
1213   return i == instance->size;
1214 }
1215
1216 static void
1217 random_instance_filler (GVariantSerialised *serialised,
1218                         gpointer            data)
1219 {
1220   RandomInstance *instance = data;
1221
1222   g_assert (instance->magic == INSTANCE_MAGIC);
1223
1224   if (serialised->type_info == NULL)
1225     serialised->type_info = instance->type_info;
1226
1227   if (serialised->size == 0)
1228     serialised->size = instance->size;
1229
1230   g_assert (serialised->type_info == instance->type_info);
1231   g_assert (serialised->size == instance->size);
1232
1233   if (serialised->data)
1234     random_instance_write (instance, serialised->data);
1235 }
1236
1237 static gsize
1238 calculate_offset_size (gsize body_size,
1239                        gsize n_offsets)
1240 {
1241   if (body_size == 0)
1242     return 0;
1243
1244   if (body_size + n_offsets <= G_MAXUINT8)
1245     return 1;
1246
1247   if (body_size + 2 * n_offsets <= G_MAXUINT16)
1248     return 2;
1249
1250   if (body_size + 4 * n_offsets <= G_MAXUINT32)
1251     return 4;
1252
1253   /* the test case won't generate anything bigger */
1254   g_assert_not_reached ();
1255 }
1256
1257 static gpointer
1258 flavoured_malloc (gsize size, gsize flavour)
1259 {
1260   g_assert (flavour < 8);
1261
1262   if (size == 0)
1263     return NULL;
1264
1265   return ((gchar *) g_malloc (size + flavour)) + flavour;
1266 }
1267
1268 static void
1269 flavoured_free (gpointer data,
1270                 gsize flavour)
1271 {
1272   if (!data)
1273     return;
1274   g_free (((gchar *) data) - flavour);
1275 }
1276
1277 static void
1278 append_offset (guchar **offset_ptr,
1279                gsize    offset,
1280                guint    offset_size)
1281 {
1282   union
1283   {
1284     guchar bytes[sizeof (gsize)];
1285     gsize integer;
1286   } tmpvalue;
1287
1288   tmpvalue.integer = GSIZE_TO_LE (offset);
1289   memcpy (*offset_ptr, tmpvalue.bytes, offset_size);
1290   *offset_ptr += offset_size;
1291 }
1292
1293 static void
1294 prepend_offset (guchar **offset_ptr,
1295                 gsize    offset,
1296                 guint    offset_size)
1297 {
1298   union
1299   {
1300     guchar bytes[sizeof (gsize)];
1301     gsize integer;
1302   } tmpvalue;
1303
1304   *offset_ptr -= offset_size;
1305   tmpvalue.integer = GSIZE_TO_LE (offset);
1306   memcpy (*offset_ptr, tmpvalue.bytes, offset_size);
1307 }
1308
1309 static void
1310 test_maybe (void)
1311 {
1312   GVariantTypeInfo *type_info;
1313   RandomInstance *instance;
1314   gsize needed_size;
1315   guchar *data;
1316
1317   instance = random_instance (NULL);
1318
1319   {
1320     const gchar *element;
1321     gchar *tmp;
1322
1323     element = g_variant_type_info_get_type_string (instance->type_info);
1324     tmp = g_strdup_printf ("m%s", element);
1325     type_info = g_variant_type_info_get (G_VARIANT_TYPE (tmp));
1326     g_free (tmp);
1327   }
1328
1329   needed_size = g_variant_serialiser_needed_size (type_info,
1330                                                   random_instance_filler,
1331                                                   NULL, 0);
1332   g_assert_cmpint (needed_size, ==, 0);
1333
1334   needed_size = g_variant_serialiser_needed_size (type_info,
1335                                                   random_instance_filler,
1336                                                   (gpointer *) &instance, 1);
1337
1338   if (instance->is_fixed_sized)
1339     g_assert_cmpint (needed_size, ==, instance->size);
1340   else
1341     g_assert_cmpint (needed_size, ==, instance->size + 1);
1342
1343   {
1344     guchar *ptr;
1345
1346     ptr = data = g_malloc (needed_size);
1347     append_instance_data (instance, &ptr);
1348
1349     if (!instance->is_fixed_sized)
1350       *ptr++ = '\0';
1351
1352     g_assert_cmpint (ptr - data, ==, needed_size);
1353   }
1354
1355   {
1356     guint alignment;
1357     guint flavour;
1358
1359     alignment = (instance->alignment & ALIGN_BITS) + 1;
1360
1361     for (flavour = 0; flavour < 8; flavour += alignment)
1362       {
1363         GVariantSerialised serialised;
1364         GVariantSerialised child;
1365
1366         serialised.type_info = type_info;
1367         serialised.data = flavoured_malloc (needed_size, flavour);
1368         serialised.size = needed_size;
1369
1370         g_variant_serialiser_serialise (serialised,
1371                                         random_instance_filler,
1372                                         (gpointer *) &instance, 1);
1373         child = g_variant_serialised_get_child (serialised, 0);
1374         g_assert (child.type_info == instance->type_info);
1375         random_instance_assert (instance, child.data, child.size);
1376         g_variant_type_info_unref (child.type_info);
1377         flavoured_free (serialised.data, flavour);
1378       }
1379   }
1380
1381   g_variant_type_info_unref (type_info);
1382   random_instance_free (instance);
1383   g_free (data);
1384 }
1385
1386 static void
1387 test_maybes (void)
1388 {
1389   guint i;
1390
1391   for (i = 0; i < 1000; i++)
1392     test_maybe ();
1393
1394   g_variant_type_info_assert_no_infos ();
1395 }
1396
1397 static void
1398 test_array (void)
1399 {
1400   GVariantTypeInfo *element_info;
1401   GVariantTypeInfo *array_info;
1402   RandomInstance **instances;
1403   gsize needed_size;
1404   gsize offset_size;
1405   guint n_children;
1406   guchar *data;
1407
1408   {
1409     gchar *element_type, *array_type;
1410
1411     element_type = random_type_string ();
1412     array_type = g_strdup_printf ("a%s", element_type);
1413
1414     element_info = g_variant_type_info_get (G_VARIANT_TYPE (element_type));
1415     array_info = g_variant_type_info_get (G_VARIANT_TYPE (array_type));
1416     g_assert (g_variant_type_info_element (array_info) == element_info);
1417
1418     g_free (element_type);
1419     g_free (array_type);
1420   }
1421
1422   {
1423     guint i;
1424
1425     n_children = g_test_rand_int_range (0, MAX_ARRAY_CHILDREN);
1426     instances = g_new (RandomInstance *, n_children);
1427     for (i = 0; i < n_children; i++)
1428       instances[i] = random_instance (element_info);
1429   }
1430
1431   needed_size = g_variant_serialiser_needed_size (array_info,
1432                                                   random_instance_filler,
1433                                                   (gpointer *) instances,
1434                                                   n_children);
1435
1436   {
1437     gsize element_fixed_size;
1438     gsize body_size = 0;
1439     guint i;
1440
1441     for (i = 0; i < n_children; i++)
1442       append_instance_size (instances[i], &body_size);
1443
1444     g_variant_type_info_query (element_info, NULL, &element_fixed_size);
1445
1446     if (!element_fixed_size)
1447       {
1448         offset_size = calculate_offset_size (body_size, n_children);
1449
1450         if (offset_size == 0)
1451           offset_size = 1;
1452       }
1453     else
1454       offset_size = 0;
1455
1456     g_assert_cmpint (needed_size, ==, body_size + n_children * offset_size);
1457   }
1458
1459   {
1460     guchar *offset_ptr, *body_ptr;
1461     guint i;
1462
1463     body_ptr = data = g_malloc (needed_size);
1464     offset_ptr = body_ptr + needed_size - offset_size * n_children;
1465
1466     for (i = 0; i < n_children; i++)
1467       {
1468         append_instance_data (instances[i], &body_ptr);
1469         append_offset (&offset_ptr, body_ptr - data, offset_size);
1470       }
1471
1472     g_assert (body_ptr == data + needed_size - offset_size * n_children);
1473     g_assert (offset_ptr == data + needed_size);
1474   }
1475
1476   {
1477     guint alignment;
1478     gsize flavour;
1479     guint i;
1480
1481     g_variant_type_info_query (array_info, &alignment, NULL);
1482     alignment = (alignment & ALIGN_BITS) + 1;
1483
1484     for (flavour = 0; flavour < 8; flavour += alignment)
1485       {
1486         GVariantSerialised serialised;
1487
1488         serialised.type_info = array_info;
1489         serialised.data = flavoured_malloc (needed_size, flavour);
1490         serialised.size = needed_size;
1491
1492         g_variant_serialiser_serialise (serialised, random_instance_filler,
1493                                         (gpointer *) instances, n_children);
1494
1495         g_assert (memcmp (serialised.data, data, serialised.size) == 0);
1496         g_assert (g_variant_serialised_n_children (serialised) == n_children);
1497
1498         for (i = 0; i < n_children; i++)
1499           {
1500             GVariantSerialised child;
1501
1502             child = g_variant_serialised_get_child (serialised, i);
1503             g_assert (child.type_info == instances[i]->type_info);
1504             random_instance_assert (instances[i], child.data, child.size);
1505             g_variant_type_info_unref (child.type_info);
1506           }
1507
1508         flavoured_free (serialised.data, flavour);
1509       }
1510   }
1511
1512   {
1513     guint i;
1514
1515     for (i = 0; i < n_children; i++)
1516       random_instance_free (instances[i]);
1517     g_free (instances);
1518   }
1519
1520   g_variant_type_info_unref (element_info);
1521   g_variant_type_info_unref (array_info);
1522   g_free (data);
1523 }
1524
1525 static void
1526 test_arrays (void)
1527 {
1528   guint i;
1529
1530   for (i = 0; i < 100; i++)
1531     test_array ();
1532
1533   g_variant_type_info_assert_no_infos ();
1534 }
1535
1536 static void
1537 test_tuple (void)
1538 {
1539   GVariantTypeInfo *type_info;
1540   RandomInstance **instances;
1541   gboolean fixed_size;
1542   gsize needed_size;
1543   gsize offset_size;
1544   guint n_children;
1545   guint alignment;
1546   guchar *data;
1547
1548   n_children = g_test_rand_int_range (0, MAX_TUPLE_CHILDREN);
1549   instances = g_new (RandomInstance *, n_children);
1550
1551   {
1552     GString *type_string;
1553     guint i;
1554
1555     fixed_size = TRUE;
1556     alignment = 0;
1557
1558     type_string = g_string_new ("(");
1559     for (i = 0; i < n_children; i++)
1560       {
1561         const gchar *str;
1562
1563         instances[i] = random_instance (NULL);
1564
1565         alignment |= instances[i]->alignment;
1566         if (!instances[i]->is_fixed_sized)
1567           fixed_size = FALSE;
1568
1569         str = g_variant_type_info_get_type_string (instances[i]->type_info);
1570         g_string_append (type_string, str);
1571       }
1572     g_string_append_c (type_string, ')');
1573
1574     type_info = g_variant_type_info_get (G_VARIANT_TYPE (type_string->str));
1575     g_string_free (type_string, TRUE);
1576   }
1577
1578   needed_size = g_variant_serialiser_needed_size (type_info,
1579                                                   random_instance_filler,
1580                                                   (gpointer *) instances,
1581                                                   n_children);
1582   {
1583     gsize body_size = 0;
1584     gsize offsets = 0;
1585     guint i;
1586
1587     for (i = 0; i < n_children; i++)
1588       {
1589         append_instance_size (instances[i], &body_size);
1590
1591         if (i != n_children - 1 && !instances[i]->is_fixed_sized)
1592           offsets++;
1593       }
1594
1595     if (fixed_size)
1596       {
1597         body_size += (-body_size) & alignment;
1598
1599         g_assert ((body_size == 0) == (n_children == 0));
1600         if (n_children == 0)
1601           body_size = 1;
1602       }
1603
1604     offset_size = calculate_offset_size (body_size, offsets);
1605     g_assert_cmpint (needed_size, ==, body_size + offsets * offset_size);
1606   }
1607
1608   {
1609     guchar *body_ptr;
1610     guchar *ofs_ptr;
1611     guint i;
1612
1613     body_ptr = data = g_malloc (needed_size);
1614     ofs_ptr = body_ptr + needed_size;
1615
1616     for (i = 0; i < n_children; i++)
1617       {
1618         append_instance_data (instances[i], &body_ptr);
1619
1620         if (i != n_children - 1 && !instances[i]->is_fixed_sized)
1621           prepend_offset (&ofs_ptr, body_ptr - data, offset_size);
1622       }
1623
1624     if (fixed_size)
1625       {
1626         while (((gsize) body_ptr) & alignment)
1627           *body_ptr++ = '\0';
1628
1629         g_assert ((body_ptr == data) == (n_children == 0));
1630         if (n_children == 0)
1631           *body_ptr++ = '\0';
1632
1633       }
1634
1635
1636     g_assert (body_ptr == ofs_ptr);
1637   }
1638
1639   {
1640     gsize flavour;
1641     guint i;
1642
1643     alignment = (alignment & ALIGN_BITS) + 1;
1644
1645     for (flavour = 0; flavour < 8; flavour += alignment)
1646       {
1647         GVariantSerialised serialised;
1648
1649         serialised.type_info = type_info;
1650         serialised.data = flavoured_malloc (needed_size, flavour);
1651         serialised.size = needed_size;
1652
1653         g_variant_serialiser_serialise (serialised, random_instance_filler,
1654                                         (gpointer *) instances, n_children);
1655
1656         g_assert (memcmp (serialised.data, data, serialised.size) == 0);
1657         g_assert (g_variant_serialised_n_children (serialised) == n_children);
1658
1659         for (i = 0; i < n_children; i++)
1660           {
1661             GVariantSerialised child;
1662
1663             child = g_variant_serialised_get_child (serialised, i);
1664             g_assert (child.type_info == instances[i]->type_info);
1665             random_instance_assert (instances[i], child.data, child.size);
1666             g_variant_type_info_unref (child.type_info);
1667           }
1668
1669         flavoured_free (serialised.data, flavour);
1670       }
1671   }
1672
1673   {
1674     guint i;
1675
1676     for (i = 0; i < n_children; i++)
1677       random_instance_free (instances[i]);
1678     g_free (instances);
1679   }
1680
1681   g_variant_type_info_unref (type_info);
1682   g_free (data);
1683 }
1684
1685 static void
1686 test_tuples (void)
1687 {
1688   guint i;
1689
1690   for (i = 0; i < 100; i++)
1691     test_tuple ();
1692
1693   g_variant_type_info_assert_no_infos ();
1694 }
1695
1696 static void
1697 test_variant (void)
1698 {
1699   GVariantTypeInfo *type_info;
1700   RandomInstance *instance;
1701   const gchar *type_string;
1702   gsize needed_size;
1703   guchar *data;
1704   gsize len;
1705
1706   type_info = g_variant_type_info_get (G_VARIANT_TYPE_VARIANT);
1707   instance = random_instance (NULL);
1708
1709   type_string = g_variant_type_info_get_type_string (instance->type_info);
1710   len = strlen (type_string);
1711
1712   needed_size = g_variant_serialiser_needed_size (type_info,
1713                                                   random_instance_filler,
1714                                                   (gpointer *) &instance, 1);
1715
1716   g_assert_cmpint (needed_size, ==, instance->size + 1 + len);
1717
1718   {
1719     guchar *ptr;
1720
1721     ptr = data = g_malloc (needed_size);
1722     append_instance_data (instance, &ptr);
1723     *ptr++ = '\0';
1724     memcpy (ptr, type_string, len);
1725     ptr += len;
1726
1727     g_assert (data + needed_size == ptr);
1728   }
1729
1730   {
1731     gsize alignment;
1732     gsize flavour;
1733
1734     /* variants are always 8-aligned */
1735     alignment = ALIGN_BITS + 1;
1736
1737     for (flavour = 0; flavour < 8; flavour += alignment)
1738       {
1739         GVariantSerialised serialised;
1740         GVariantSerialised child;
1741
1742         serialised.type_info = type_info;
1743         serialised.data = flavoured_malloc (needed_size, flavour);
1744         serialised.size = needed_size;
1745
1746         g_variant_serialiser_serialise (serialised, random_instance_filler,
1747                                         (gpointer *) &instance, 1);
1748
1749         g_assert (memcmp (serialised.data, data, serialised.size) == 0);
1750         g_assert (g_variant_serialised_n_children (serialised) == 1);
1751
1752         child = g_variant_serialised_get_child (serialised, 0);
1753         g_assert (child.type_info == instance->type_info);
1754         random_instance_check (instance, child.data, child.size);
1755
1756         g_variant_type_info_unref (child.type_info);
1757         flavoured_free (serialised.data, flavour);
1758       }
1759   }
1760
1761   g_variant_type_info_unref (type_info);
1762   random_instance_free (instance);
1763   g_free (data);
1764 }
1765
1766 static void
1767 test_variants (void)
1768 {
1769   guint i;
1770
1771   for (i = 0; i < 100; i++)
1772     test_variant ();
1773
1774   g_variant_type_info_assert_no_infos ();
1775 }
1776
1777 static void
1778 test_strings (void)
1779 {
1780   struct {
1781     guint flags;
1782     guint size;
1783     gconstpointer data;
1784   } test_cases[] = {
1785 #define is_nval           0
1786 #define is_string         1
1787 #define is_objpath        is_string | 2
1788 #define is_sig            is_string | 4
1789     { is_sig,       1, "" },
1790     { is_nval,      0, NULL },
1791     { is_nval,     13, "hello\xffworld!" },
1792     { is_string,   13, "hello world!" },
1793     { is_nval,     13, "hello world\0" },
1794     { is_nval,     13, "hello\0world!" },
1795     { is_nval,     12, "hello world!" },
1796
1797     { is_objpath,   2, "/" },
1798     { is_objpath,   3, "/a" },
1799     { is_string,    3, "//" },
1800     { is_objpath,  11, "/some/path" },
1801     { is_string,   12, "/some/path/" },
1802     { is_nval,     11, "/some\0path" },
1803     { is_string,   11, "/some\\path" },
1804     { is_string,   12, "/some//path" },
1805     { is_string,   12, "/some-/path" },
1806
1807     { is_sig,       2, "i" },
1808     { is_sig,       2, "s" },
1809     { is_sig,       5, "(si)" },
1810     { is_string,    4, "(si" },
1811     { is_string,    2, "*" },
1812     { is_sig,       3, "ai" },
1813     { is_string,    3, "mi" },
1814     { is_string,    2, "r" },
1815     { is_sig,      15, "(yyy{sv}ssiai)" },
1816     { is_string,   16, "(yyy{yv}ssiai))" },
1817     { is_string,   15, "(yyy{vv}ssiai)" },
1818     { is_string,   15, "(yyy{sv)ssiai}" }
1819   };
1820   guint i;
1821
1822   for (i = 0; i < G_N_ELEMENTS (test_cases); i++)
1823     {
1824       guint flags;
1825
1826       flags = g_variant_serialiser_is_string (test_cases[i].data,
1827                                               test_cases[i].size)
1828         ? 1 : 0;
1829
1830       flags |= g_variant_serialiser_is_object_path (test_cases[i].data,
1831                                                     test_cases[i].size)
1832         ? 2 : 0;
1833
1834       flags |= g_variant_serialiser_is_signature (test_cases[i].data,
1835                                                   test_cases[i].size)
1836         ? 4 : 0;
1837
1838       g_assert (flags == test_cases[i].flags);
1839     }
1840 }
1841
1842 typedef struct _TreeInstance TreeInstance;
1843 struct _TreeInstance
1844 {
1845   GVariantTypeInfo *info;
1846
1847   TreeInstance **children;
1848   gsize n_children;
1849
1850   union {
1851     guint64 integer;
1852     gdouble floating;
1853     gchar string[32];
1854   } data;
1855   gsize data_size;
1856 };
1857
1858 static GVariantType *
1859 make_random_definite_type (int depth)
1860 {
1861   GString *description;
1862   GString *type_string;
1863   GVariantType *type;
1864
1865   description = g_string_new (NULL);
1866   type_string = g_string_new (NULL);
1867   type = append_type_string (type_string, description, TRUE, depth);
1868   g_string_free (description, TRUE);
1869   g_string_free (type_string, TRUE);
1870
1871   return type;
1872 }
1873
1874 static void
1875 make_random_string (gchar              *string,
1876                     gsize               size,
1877                     const GVariantType *type)
1878 {
1879   gint i;
1880
1881   /* create strings that are valid signature strings */
1882 #define good_chars "bynqiuxthdsog"
1883
1884   for (i = 0; i < size - 1; i++)
1885     string[i] = good_chars[g_test_rand_int_range (0, strlen (good_chars))];
1886   string[i] = '\0';
1887
1888   /* in case we need an object path, prefix a '/' */
1889   if (*g_variant_type_peek_string (type) == 'o')
1890     string[0] = '/';
1891
1892 #undef good_chars
1893 }
1894
1895 static TreeInstance *
1896 tree_instance_new (const GVariantType *type,
1897                    int                 depth)
1898 {
1899   const GVariantType *child_type = NULL;
1900   GVariantType *mytype = NULL;
1901   TreeInstance *instance;
1902   gboolean is_tuple_type;
1903
1904   if (type == NULL)
1905     type = mytype = make_random_definite_type (depth);
1906
1907   instance = g_slice_new (TreeInstance);
1908   instance->info = g_variant_type_info_get (type);
1909   instance->children = NULL;
1910   instance->n_children = 0;
1911   instance->data_size = 0;
1912
1913   is_tuple_type = FALSE;
1914
1915   switch (*g_variant_type_peek_string (type))
1916     {
1917     case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
1918       instance->n_children = g_test_rand_int_range (0, 2);
1919       child_type = g_variant_type_element (type);
1920       break;
1921
1922     case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
1923       instance->n_children = g_test_rand_int_range (0, MAX_ARRAY_CHILDREN);
1924       child_type = g_variant_type_element (type);
1925       break;
1926
1927     case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
1928     case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
1929       instance->n_children = g_variant_type_n_items (type);
1930       child_type = g_variant_type_first (type);
1931       is_tuple_type = TRUE;
1932       break;
1933
1934     case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
1935       instance->n_children = 1;
1936       child_type = NULL;
1937       break;
1938
1939     case 'b':
1940       instance->data.integer = g_test_rand_int_range (0, 2);
1941       instance->data_size = 1;
1942       break;
1943
1944     case 'y':
1945       instance->data.integer = g_test_rand_int ();
1946       instance->data_size = 1;
1947       break;
1948
1949     case 'n': case 'q':
1950       instance->data.integer = g_test_rand_int ();
1951       instance->data_size = 2;
1952       break;
1953
1954     case 'i': case 'u': case 'h':
1955       instance->data.integer = g_test_rand_int ();
1956       instance->data_size = 4;
1957       break;
1958
1959     case 'x': case 't':
1960       instance->data.integer = g_test_rand_int ();
1961       instance->data.integer <<= 32;
1962       instance->data.integer |= (guint32) g_test_rand_int ();
1963       instance->data_size = 8;
1964       break;
1965
1966     case 'd':
1967       instance->data.floating = g_test_rand_double ();
1968       instance->data_size = 8;
1969       break;
1970
1971     case 's': case 'o': case 'g':
1972       instance->data_size = g_test_rand_int_range (10, 20);
1973       make_random_string (instance->data.string, instance->data_size, type);
1974       break;
1975     }
1976
1977   if (instance->data_size == 0)
1978     /* no data -> it is a container */
1979     {
1980       guint i;
1981
1982       instance->children = g_new (TreeInstance *, instance->n_children);
1983
1984       for (i = 0; i < instance->n_children; i++)
1985         {
1986           instance->children[i] = tree_instance_new (child_type, depth - 1);
1987
1988           if (is_tuple_type)
1989             child_type = g_variant_type_next (child_type);
1990         }
1991
1992       g_assert (!is_tuple_type || child_type == NULL);
1993     }
1994
1995   g_variant_type_free (mytype);
1996
1997   return instance;
1998 }
1999
2000 static void
2001 tree_instance_free (TreeInstance *instance)
2002 {
2003   gint i;
2004
2005   g_variant_type_info_unref (instance->info);
2006   for (i = 0; i < instance->n_children; i++)
2007     tree_instance_free (instance->children[i]);
2008   g_free (instance->children);
2009   g_slice_free (TreeInstance, instance);
2010 }
2011
2012 static gboolean i_am_writing_byteswapped;
2013
2014 static void
2015 tree_filler (GVariantSerialised *serialised,
2016              gpointer            data)
2017 {
2018   TreeInstance *instance = data;
2019
2020   if (serialised->type_info == NULL)
2021     serialised->type_info = instance->info;
2022
2023   if (instance->data_size == 0)
2024     /* is a container */
2025     {
2026       if (serialised->size == 0)
2027         serialised->size =
2028           g_variant_serialiser_needed_size (instance->info, tree_filler,
2029                                             (gpointer *) instance->children,
2030                                             instance->n_children);
2031
2032       if (serialised->data)
2033         g_variant_serialiser_serialise (*serialised, tree_filler,
2034                                         (gpointer *) instance->children,
2035                                         instance->n_children);
2036     }
2037   else
2038     /* it is a leaf */
2039     {
2040       if (serialised->size == 0)
2041         serialised->size = instance->data_size;
2042
2043       if (serialised->data)
2044         {
2045           switch (instance->data_size)
2046             {
2047             case 1:
2048               *serialised->data = instance->data.integer;
2049               break;
2050
2051             case 2:
2052               {
2053                 guint16 value = instance->data.integer;
2054
2055                 if (i_am_writing_byteswapped)
2056                   value = GUINT16_SWAP_LE_BE (value);
2057
2058                 *(guint16 *) serialised->data = value;
2059               }
2060               break;
2061
2062             case 4:
2063               {
2064                 guint32 value = instance->data.integer;
2065
2066                 if (i_am_writing_byteswapped)
2067                   value = GUINT32_SWAP_LE_BE (value);
2068
2069                 *(guint32 *) serialised->data = value;
2070               }
2071               break;
2072
2073             case 8:
2074               {
2075                 guint64 value = instance->data.integer;
2076
2077                 if (i_am_writing_byteswapped)
2078                   value = GUINT64_SWAP_LE_BE (value);
2079
2080                 *(guint64 *) serialised->data = value;
2081               }
2082               break;
2083
2084             default:
2085               memcpy (serialised->data,
2086                       instance->data.string,
2087                       instance->data_size);
2088               break;
2089             }
2090         }
2091     }
2092 }
2093
2094 static gboolean
2095 check_tree (TreeInstance       *instance,
2096             GVariantSerialised  serialised)
2097 {
2098   if (instance->info != serialised.type_info)
2099     return FALSE;
2100
2101   if (instance->data_size == 0)
2102     /* is a container */
2103     {
2104       gint i;
2105
2106       if (g_variant_serialised_n_children (serialised) !=
2107           instance->n_children)
2108         return FALSE;
2109
2110       for (i = 0; i < instance->n_children; i++)
2111         {
2112           GVariantSerialised child;
2113           gpointer data = NULL;
2114           gboolean ok;
2115
2116           child = g_variant_serialised_get_child (serialised, i);
2117           if (child.size && child.data == NULL)
2118             child.data = data = g_malloc0 (child.size);
2119           ok = check_tree (instance->children[i], child);
2120           g_variant_type_info_unref (child.type_info);
2121           g_free (data);
2122
2123           if (!ok)
2124             return FALSE;
2125         }
2126
2127       return TRUE;
2128     }
2129   else
2130     /* it is a leaf */
2131     {
2132       switch (instance->data_size)
2133         {
2134         case 1:
2135           g_assert (serialised.size == 1);
2136           return *(guint8 *) serialised.data ==
2137                   (guint8) instance->data.integer;
2138
2139         case 2:
2140           g_assert (serialised.size == 2);
2141           return *(guint16 *) serialised.data ==
2142                   (guint16) instance->data.integer;
2143
2144         case 4:
2145           g_assert (serialised.size == 4);
2146           return *(guint32 *) serialised.data ==
2147                   (guint32) instance->data.integer;
2148
2149         case 8:
2150           g_assert (serialised.size == 8);
2151           return *(guint64 *) serialised.data ==
2152                   (guint64) instance->data.integer;
2153
2154         default:
2155           if (serialised.size != instance->data_size)
2156             return FALSE;
2157
2158           return memcmp (serialised.data,
2159                          instance->data.string,
2160                          instance->data_size) == 0;
2161         }
2162     }
2163 }
2164
2165 static void
2166 serialise_tree (TreeInstance       *tree,
2167                 GVariantSerialised *serialised)
2168 {
2169   GVariantSerialised empty = {  };
2170
2171   *serialised = empty;
2172   tree_filler (serialised, tree);
2173   serialised->data = g_malloc (serialised->size);
2174   tree_filler (serialised, tree);
2175 }
2176
2177 static void
2178 test_byteswap (void)
2179 {
2180   GVariantSerialised one, two;
2181   TreeInstance *tree;
2182
2183   tree = tree_instance_new (NULL, 3);
2184   serialise_tree (tree, &one);
2185
2186   i_am_writing_byteswapped = TRUE;
2187   serialise_tree (tree, &two);
2188   i_am_writing_byteswapped = FALSE;
2189
2190   g_variant_serialised_byteswap (two);
2191
2192   g_assert_cmpint (one.size, ==, two.size);
2193   g_assert (memcmp (one.data, two.data, one.size) == 0);
2194
2195   tree_instance_free (tree);
2196   g_free (one.data);
2197   g_free (two.data);
2198 }
2199
2200 static void
2201 test_byteswaps (void)
2202 {
2203   int i;
2204
2205   for (i = 0; i < 200; i++)
2206     test_byteswap ();
2207
2208   g_variant_type_info_assert_no_infos ();
2209 }
2210
2211 static void
2212 test_fuzz (gdouble *fuzziness)
2213 {
2214   GVariantSerialised serialised;
2215   TreeInstance *tree;
2216
2217   /* make an instance */
2218   tree = tree_instance_new (NULL, 3);
2219
2220   /* serialise it */
2221   serialise_tree (tree, &serialised);
2222
2223   g_assert (g_variant_serialised_is_normal (serialised));
2224   g_assert (check_tree (tree, serialised));
2225
2226   if (serialised.size)
2227     {
2228       gboolean fuzzed = FALSE;
2229       gboolean a, b;
2230
2231       while (!fuzzed)
2232         {
2233           gint i;
2234
2235           for (i = 0; i < serialised.size; i++)
2236             if (randomly (*fuzziness))
2237               {
2238                 serialised.data[i] += g_test_rand_int_range (1, 256);
2239                 fuzzed = TRUE;
2240               }
2241         }
2242
2243       /* at least one byte in the serialised data has changed.
2244        *
2245        * this means that at least one of the following is true:
2246        *
2247        *    - the serialised data now represents a different value:
2248        *        check_tree() will return FALSE
2249        *
2250        *    - the serialised data is in non-normal form:
2251        *        g_variant_serialiser_is_normal() will return FALSE
2252        *
2253        * we always do both checks to increase exposure of the serialiser
2254        * to corrupt data.
2255        */
2256       a = g_variant_serialised_is_normal (serialised);
2257       b = check_tree (tree, serialised);
2258
2259       g_assert (!a || !b);
2260     }
2261
2262   tree_instance_free (tree);
2263   g_free (serialised.data);
2264 }
2265
2266
2267 static void
2268 test_fuzzes (gpointer data)
2269 {
2270   gdouble fuzziness;
2271   int i;
2272
2273   fuzziness = GPOINTER_TO_INT (data) / 100.;
2274
2275   for (i = 0; i < 200; i++)
2276     test_fuzz (&fuzziness);
2277
2278   g_variant_type_info_assert_no_infos ();
2279 }
2280
2281 static GVariant *
2282 tree_instance_get_gvariant (TreeInstance *tree)
2283 {
2284   const GVariantType *type;
2285   GVariant *result;
2286
2287   type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
2288
2289   switch (g_variant_type_info_get_type_char (tree->info))
2290     {
2291     case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
2292       {
2293         const GVariantType *child_type;
2294         GVariant *child;
2295
2296         if (tree->n_children)
2297           child = tree_instance_get_gvariant (tree->children[0]);
2298         else
2299           child = NULL;
2300
2301         child_type = g_variant_type_element (type);
2302
2303         if (child != NULL && randomly (0.5))
2304           child_type = NULL;
2305
2306         result = g_variant_new_maybe (child_type, child);
2307       }
2308       break;
2309
2310     case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
2311       {
2312         const GVariantType *child_type;
2313         GVariant **children;
2314         gint i;
2315
2316         children = g_new (GVariant *, tree->n_children);
2317         for (i = 0; i < tree->n_children; i++)
2318           children[i] = tree_instance_get_gvariant (tree->children[i]);
2319
2320         child_type = g_variant_type_element (type);
2321
2322         if (i > 0 && randomly (0.5))
2323           child_type = NULL;
2324
2325         result = g_variant_new_array (child_type, children, tree->n_children);
2326         g_free (children);
2327       }
2328       break;
2329
2330     case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
2331       {
2332         GVariant **children;
2333         gint i;
2334
2335         children = g_new (GVariant *, tree->n_children);
2336         for (i = 0; i < tree->n_children; i++)
2337           children[i] = tree_instance_get_gvariant (tree->children[i]);
2338
2339         result = g_variant_new_tuple (children, tree->n_children);
2340         g_free (children);
2341       }
2342       break;
2343
2344     case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
2345       {
2346         GVariant *key, *val;
2347
2348         g_assert (tree->n_children == 2);
2349
2350         key = tree_instance_get_gvariant (tree->children[0]);
2351         val = tree_instance_get_gvariant (tree->children[1]);
2352
2353         result = g_variant_new_dict_entry (key, val);
2354       }
2355       break;
2356
2357     case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
2358       {
2359         GVariant *value;
2360
2361         g_assert (tree->n_children == 1);
2362
2363         value = tree_instance_get_gvariant (tree->children[0]);
2364         result = g_variant_new_variant (value);
2365       }
2366       break;
2367
2368     case 'b':
2369       result = g_variant_new_boolean (tree->data.integer > 0);
2370       break;
2371
2372     case 'y':
2373       result = g_variant_new_byte (tree->data.integer);
2374       break;
2375
2376     case 'n':
2377       result = g_variant_new_int16 (tree->data.integer);
2378       break;
2379
2380     case 'q':
2381       result = g_variant_new_uint16 (tree->data.integer);
2382       break;
2383
2384     case 'i':
2385       result = g_variant_new_int32 (tree->data.integer);
2386       break;
2387
2388     case 'u':
2389       result = g_variant_new_uint32 (tree->data.integer);
2390       break;
2391
2392     case 'x':
2393       result = g_variant_new_int64 (tree->data.integer);
2394       break;
2395
2396     case 't':
2397       result = g_variant_new_uint64 (tree->data.integer);
2398       break;
2399
2400     case 'h':
2401       result = g_variant_new_handle (tree->data.integer);
2402       break;
2403
2404     case 'd':
2405       result = g_variant_new_double (tree->data.floating);
2406       break;
2407
2408     case 's':
2409       result = g_variant_new_string (tree->data.string);
2410       break;
2411
2412     case 'o':
2413       result = g_variant_new_object_path (tree->data.string);
2414       break;
2415
2416     case 'g':
2417       result = g_variant_new_signature (tree->data.string);
2418       break;
2419
2420     default:
2421       g_assert_not_reached ();
2422     }
2423
2424   return result;
2425 }
2426
2427 static gboolean
2428 tree_instance_check_gvariant (TreeInstance *tree,
2429                               GVariant     *value)
2430 {
2431   const GVariantType *type;
2432
2433   type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
2434   g_assert (g_variant_is_of_type (value, type));
2435
2436   switch (g_variant_type_info_get_type_char (tree->info))
2437     {
2438     case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
2439       {
2440         GVariant *child;
2441         gboolean equal;
2442
2443         child = g_variant_get_maybe (value);
2444
2445         if (child != NULL && tree->n_children == 1)
2446           equal = tree_instance_check_gvariant (tree->children[0], child);
2447         else if (child == NULL && tree->n_children == 0)
2448           equal = TRUE;
2449         else
2450           equal = FALSE;
2451
2452         if (child != NULL)
2453           g_variant_unref (child);
2454
2455         return equal;
2456       }
2457       break;
2458
2459     case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
2460     case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
2461     case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
2462       {
2463         gsize i;
2464
2465         if (g_variant_n_children (value) != tree->n_children)
2466           return FALSE;
2467
2468         for (i = 0; i < tree->n_children; i++)
2469           {
2470             GVariant *child;
2471             gboolean equal;
2472
2473             child = g_variant_get_child_value (value, i);
2474             equal = tree_instance_check_gvariant (tree->children[i], child);
2475             g_variant_unref (child);
2476
2477             if (!equal)
2478               return FALSE;
2479           }
2480
2481         return TRUE;
2482       }
2483       break;
2484
2485     case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
2486       {
2487         const gchar *str1, *str2;
2488         GVariant *child;
2489         gboolean equal;
2490
2491         child = g_variant_get_variant (value);
2492         str1 = g_variant_get_type_string (child);
2493         str2 = g_variant_type_info_get_type_string (tree->children[0]->info);
2494         /* GVariant only keeps one copy of type strings around */
2495         equal = str1 == str2 &&
2496                 tree_instance_check_gvariant (tree->children[0], child);
2497
2498         g_variant_unref (child);
2499
2500         return equal;
2501       }
2502       break;
2503
2504     case 'b':
2505       return g_variant_get_boolean (value) == tree->data.integer;
2506
2507     case 'y':
2508       return g_variant_get_byte (value) == (guchar) tree->data.integer;
2509
2510     case 'n':
2511       return g_variant_get_int16 (value) == (gint16) tree->data.integer;
2512
2513     case 'q':
2514       return g_variant_get_uint16 (value) == (guint16) tree->data.integer;
2515
2516     case 'i':
2517       return g_variant_get_int32 (value) == (gint32) tree->data.integer;
2518
2519     case 'u':
2520       return g_variant_get_uint32 (value) == (guint32) tree->data.integer;
2521
2522     case 'x':
2523       return g_variant_get_int64 (value) == (gint64) tree->data.integer;
2524
2525     case 't':
2526       return g_variant_get_uint64 (value) == (guint64) tree->data.integer;
2527
2528     case 'h':
2529       return g_variant_get_handle (value) == (gint32) tree->data.integer;
2530
2531     case 'd':
2532       {
2533         gdouble floating = g_variant_get_double (value);
2534
2535         return memcmp (&floating, &tree->data.floating, sizeof floating) == 0;
2536       }
2537
2538     case 's':
2539     case 'o':
2540     case 'g':
2541       return strcmp (g_variant_get_string (value, NULL),
2542                      tree->data.string) == 0;
2543
2544     default:
2545       g_assert_not_reached ();
2546     }
2547 }
2548
2549 static void
2550 tree_instance_build_gvariant (TreeInstance    *tree,
2551                               GVariantBuilder *builder,
2552                               gboolean         guess_ok)
2553 {
2554   const GVariantType *type;
2555
2556   type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
2557
2558   if (g_variant_type_is_container (type))
2559     {
2560       gsize i;
2561
2562       /* force GVariantBuilder to guess the type half the time */
2563       if (guess_ok && randomly (0.5))
2564         {
2565           if (g_variant_type_is_array (type) && tree->n_children)
2566             type = G_VARIANT_TYPE_ARRAY;
2567
2568           if (g_variant_type_is_maybe (type) && tree->n_children)
2569             type = G_VARIANT_TYPE_MAYBE;
2570
2571           if (g_variant_type_is_tuple (type))
2572             type = G_VARIANT_TYPE_TUPLE;
2573
2574           if (g_variant_type_is_dict_entry (type))
2575             type = G_VARIANT_TYPE_DICT_ENTRY;
2576         }
2577       else
2578         guess_ok = FALSE;
2579
2580       g_variant_builder_open (builder, type);
2581
2582       for (i = 0; i < tree->n_children; i++)
2583         tree_instance_build_gvariant (tree->children[i], builder, guess_ok);
2584
2585       g_variant_builder_close (builder);
2586     }
2587   else
2588     g_variant_builder_add_value (builder, tree_instance_get_gvariant (tree));
2589 }
2590
2591
2592 static gboolean
2593 tree_instance_check_iter (TreeInstance *tree,
2594                           GVariantIter *iter)
2595 {
2596   GVariant *value;
2597
2598   value = g_variant_iter_next_value (iter);
2599
2600   if (g_variant_is_container (value))
2601     {
2602       gsize i;
2603
2604       iter = g_variant_iter_new (value);
2605       g_variant_unref (value);
2606
2607       if (g_variant_iter_n_children (iter) != tree->n_children)
2608         {
2609           g_variant_iter_free (iter);
2610           return FALSE;
2611         }
2612
2613       for (i = 0; i < tree->n_children; i++)
2614         if (!tree_instance_check_iter (tree->children[i], iter))
2615           {
2616             g_variant_iter_free (iter);
2617             return FALSE;
2618           }
2619
2620       g_assert (g_variant_iter_next_value (iter) == NULL);
2621       g_variant_iter_free (iter);
2622
2623       return TRUE;
2624     }
2625
2626   else
2627     {
2628       gboolean equal;
2629
2630       equal = tree_instance_check_gvariant (tree, value);
2631       g_variant_unref (value);
2632
2633       return equal;
2634     }
2635 }
2636
2637 static void
2638 test_container (void)
2639 {
2640   TreeInstance *tree;
2641   GVariant *value;
2642   gchar *s1, *s2;
2643
2644   tree = tree_instance_new (NULL, 3);
2645   value = g_variant_ref_sink (tree_instance_get_gvariant (tree));
2646
2647   s1 = g_variant_print (value, TRUE);
2648   g_assert (tree_instance_check_gvariant (tree, value));
2649
2650   g_variant_get_data (value);
2651
2652   s2 = g_variant_print (value, TRUE);
2653   g_assert (tree_instance_check_gvariant (tree, value));
2654
2655   g_assert_cmpstr (s1, ==, s2);
2656
2657   if (g_variant_is_container (value))
2658     {
2659       GVariantBuilder builder;
2660       GVariantIter iter;
2661       GVariant *built;
2662       GVariant *val;
2663       gchar *s3;
2664
2665       g_variant_builder_init (&builder, G_VARIANT_TYPE_VARIANT);
2666       tree_instance_build_gvariant (tree, &builder, TRUE);
2667       built = g_variant_builder_end (&builder);
2668       g_variant_ref_sink (built);
2669       g_variant_get_data (built);
2670       val = g_variant_get_variant (built);
2671
2672       s3 = g_variant_print (val, TRUE);
2673       g_assert_cmpstr (s1, ==, s3);
2674
2675       g_variant_iter_init (&iter, built);
2676       g_assert (tree_instance_check_iter (tree, &iter));
2677       g_assert (g_variant_iter_next_value (&iter) == NULL);
2678
2679       g_variant_unref (built);
2680       g_variant_unref (val);
2681       g_free (s3);
2682     }
2683
2684   tree_instance_free (tree);
2685   g_variant_unref (value);
2686   g_free (s2);
2687   g_free (s1);
2688 }
2689
2690 static void
2691 test_utf8 (void)
2692 {
2693   const gchar invalid[] = "hello\xffworld";
2694   GVariant *value;
2695
2696   /* ensure that the test data is not valid utf8... */
2697   g_assert (!g_utf8_validate (invalid, -1, NULL));
2698
2699   /* load the data untrusted */
2700   value = g_variant_new_from_data (G_VARIANT_TYPE_STRING,
2701                                    invalid, sizeof invalid,
2702                                    FALSE, NULL, NULL);
2703
2704   /* ensure that the problem is caught and we get valid UTF-8 */
2705   g_assert (g_utf8_validate (g_variant_get_string (value, NULL), -1, NULL));
2706   g_variant_unref (value);
2707
2708
2709   /* now load it trusted */
2710   value = g_variant_new_from_data (G_VARIANT_TYPE_STRING,
2711                                    invalid, sizeof invalid,
2712                                    TRUE, NULL, NULL);
2713
2714   /* ensure we get the invalid data (ie: make sure that time wasn't
2715    * wasted on validating data that was marked as trusted)
2716    */
2717   g_assert (g_variant_get_string (value, NULL) == invalid);
2718   g_variant_unref (value);
2719 }
2720
2721 static void
2722 test_containers (void)
2723 {
2724   gint i;
2725
2726   for (i = 0; i < 100; i++)
2727     {
2728       test_container ();
2729     }
2730
2731   g_variant_type_info_assert_no_infos ();
2732 }
2733
2734 static void
2735 test_format_strings (void)
2736 {
2737   GVariantType *type;
2738   const gchar *end;
2739
2740   g_assert (g_variant_format_string_scan ("i", NULL, &end) && *end == '\0');
2741   g_assert (g_variant_format_string_scan ("@i", NULL, &end) && *end == '\0');
2742   g_assert (g_variant_format_string_scan ("@ii", NULL, &end) && *end == 'i');
2743   g_assert (g_variant_format_string_scan ("^a&s", NULL, &end) && *end == '\0');
2744   g_assert (g_variant_format_string_scan ("(^as)", NULL, &end) &&
2745             *end == '\0');
2746   g_assert (!g_variant_format_string_scan ("(^s)", NULL, &end));
2747   g_assert (!g_variant_format_string_scan ("(^a)", NULL, &end));
2748   g_assert (!g_variant_format_string_scan ("(z)", NULL, &end));
2749   g_assert (!g_variant_format_string_scan ("az", NULL, &end));
2750   g_assert (!g_variant_format_string_scan ("{**}", NULL, &end));
2751   g_assert (!g_variant_format_string_scan ("{@**}", NULL, &end));
2752   g_assert (g_variant_format_string_scan ("{@y*}", NULL, &end) &&
2753             *end == '\0');
2754   g_assert (g_variant_format_string_scan ("{yv}", NULL, &end) &&
2755             *end == '\0');
2756   g_assert (!g_variant_format_string_scan ("{&?v}", NULL, &end));
2757   g_assert (g_variant_format_string_scan ("{@?v}", NULL, &end) &&
2758             *end == '\0');
2759   g_assert (!g_variant_format_string_scan ("{&@sv}", NULL, &end));
2760   g_assert (!g_variant_format_string_scan ("{@&sv}", NULL, &end));
2761   g_assert (g_variant_format_string_scan ("{&sv}", NULL, &end) &&
2762             *end == '\0');
2763   g_assert (!g_variant_format_string_scan ("{vv}", NULL, &end));
2764   g_assert (!g_variant_format_string_scan ("{y}", NULL, &end));
2765   g_assert (!g_variant_format_string_scan ("{yyy}", NULL, &end));
2766   g_assert (!g_variant_format_string_scan ("{ya}", NULL, &end));
2767   g_assert (g_variant_format_string_scan ("&s", NULL, &end) && *end == '\0');
2768   g_assert (!g_variant_format_string_scan ("&as", NULL, &end));
2769   g_assert (!g_variant_format_string_scan ("@z", NULL, &end));
2770   g_assert (!g_variant_format_string_scan ("az", NULL, &end));
2771   g_assert (!g_variant_format_string_scan ("a&s", NULL, &end));
2772
2773   type = g_variant_format_string_scan_type ("mm(@xy^a&s*?@?)", NULL, &end);
2774   g_assert (type && *end == '\0');
2775   g_assert (g_variant_type_equal (type, G_VARIANT_TYPE ("mm(xyas*?\?)")));
2776   g_variant_type_free (type);
2777
2778   type = g_variant_format_string_scan_type ("mm(@xy^a&*?@?)", NULL, NULL);
2779   g_assert (type == NULL);
2780 }
2781
2782 static void
2783 exit_on_abort (int signal)
2784 {
2785   exit (signal);
2786 }
2787
2788 static gboolean
2789 do_failed_test (const gchar *pattern)
2790 {
2791   if (g_test_trap_fork (1000000, G_TEST_TRAP_SILENCE_STDERR))
2792     {
2793       signal (SIGABRT, exit_on_abort);
2794       return TRUE;
2795     }
2796
2797   g_test_trap_assert_failed ();
2798   g_test_trap_assert_stderr (pattern);
2799
2800   return FALSE;
2801 }
2802
2803 static void
2804 test_invalid_varargs (void)
2805 {
2806   if (do_failed_test ("*GVariant format string*"))
2807     {
2808       g_variant_new ("z");
2809       abort ();
2810     }
2811
2812   if (do_failed_test ("*valid GVariant format string as a prefix*"))
2813     {
2814       const gchar *end;
2815
2816       g_variant_new_va ("z", &end, NULL);
2817       abort ();
2818     }
2819
2820   if (do_failed_test ("*type of `q' but * has a type of `y'*"))
2821     {
2822       g_variant_get (g_variant_new ("y", 'a'), "q");
2823       abort ();
2824     }
2825 }
2826
2827 static void
2828 check_and_free (GVariant    *value,
2829                 const gchar *str)
2830 {
2831   gchar *valstr = g_variant_print (value, FALSE);
2832   g_assert_cmpstr (str, ==, valstr);
2833   g_variant_unref (value);
2834   g_free (valstr);
2835 }
2836
2837 static void
2838 test_varargs (void)
2839 {
2840   {
2841     GVariantBuilder array;
2842
2843     g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
2844     g_variant_builder_add (&array, "{sv}", "size",
2845                            g_variant_new ("(ii)", 800, 600));
2846     g_variant_builder_add (&array, "{sv}", "title",
2847                            g_variant_new_string ("Test case"));
2848     g_variant_builder_add_value (&array,
2849       g_variant_new_dict_entry (g_variant_new_string ("temperature"),
2850                                 g_variant_new_variant (
2851                                   g_variant_new_double (37.5))));
2852     check_and_free (g_variant_new ("(ma{sv}m(a{sv})ma{sv}ii)",
2853                                    NULL, FALSE, NULL, &array, 7777, 8888),
2854                     "(nothing, nothing, {'size': <(800, 600)>, "
2855                                         "'title': <'Test case'>, "
2856                                         "'temperature': <37.5>}, "
2857                      "7777, 8888)");
2858
2859     check_and_free (g_variant_new ("(imimimmimmimmi)",
2860                                    123,
2861                                    FALSE, 321,
2862                                    TRUE, 123,
2863                                    FALSE, TRUE, 321,
2864                                    TRUE, FALSE, 321,
2865                                    TRUE, TRUE, 123),
2866                     "(123, nothing, 123, nothing, just nothing, 123)");
2867
2868     check_and_free (g_variant_new ("(ybnixd)",
2869                                    'a', 1, 22, 33, (guint64) 44, 5.5),
2870                     "(0x61, true, 22, 33, 44, 5.5)");
2871
2872     check_and_free (g_variant_new ("(@y?*rv)",
2873                                    g_variant_new ("y", 'a'),
2874                                    g_variant_new ("y", 'b'),
2875                                    g_variant_new ("y", 'c'),
2876                                    g_variant_new ("(y)", 'd'),
2877                                    g_variant_new ("y", 'e')),
2878                     "(0x61, 0x62, 0x63, (0x64,), <byte 0x65>)");
2879   }
2880
2881   {
2882     GVariantBuilder array;
2883     GVariantIter iter;
2884     GVariant *value;
2885     gchar *number;
2886     gboolean just;
2887     gint i, val;
2888
2889     g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
2890     for (i = 0; i < 100; i++)
2891       {
2892         number = g_strdup_printf ("%d", i);
2893         g_variant_builder_add (&array, "s", number);
2894         g_free (number);
2895       }
2896
2897     value = g_variant_builder_end (&array);
2898     g_variant_iter_init (&iter, value);
2899
2900     i = 0;
2901     while (g_variant_iter_loop (&iter, "s", &number))
2902       {
2903         gchar *check = g_strdup_printf ("%d", i++);
2904         g_assert_cmpstr (number, ==, check);
2905         g_free (check);
2906       }
2907     g_assert (number == NULL);
2908     g_assert (i == 100);
2909
2910     g_variant_unref (value);
2911
2912     g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
2913     for (i = 0; i < 100; i++)
2914       g_variant_builder_add (&array, "mi", i % 2 == 0, i);
2915     value = g_variant_builder_end (&array);
2916
2917     i = 0;
2918     g_variant_iter_init (&iter, value);
2919     while (g_variant_iter_loop (&iter, "mi", NULL, &val))
2920       g_assert (val == i++ || val == 0);
2921     g_assert (i == 100);
2922
2923     i = 0;
2924     g_variant_iter_init (&iter, value);
2925     while (g_variant_iter_loop (&iter, "mi", &just, &val))
2926       {
2927         gint this = i++;
2928
2929         if (this % 2 == 0)
2930           {
2931             g_assert (just);
2932             g_assert (val == this);
2933           }
2934         else
2935           {
2936             g_assert (!just);
2937             g_assert (val == 0);
2938           }
2939       }
2940     g_assert (i == 100);
2941
2942     g_variant_unref (value);
2943   }
2944
2945   {
2946     const gchar *strvector[] = {"/hello", "/world", NULL};
2947     const gchar *test_strs[] = {"/foo", "/bar", "/baz" };
2948     GVariantBuilder builder;
2949     GVariantIter *array;
2950     GVariantIter tuple;
2951     const gchar **strv;
2952     gchar **my_strv;
2953     GVariant *value;
2954     gchar *str;
2955     gint i;
2956
2957     g_variant_builder_init (&builder, G_VARIANT_TYPE ("ao"));
2958     g_variant_builder_add (&builder, "o", "/foo");
2959     g_variant_builder_add (&builder, "o", "/bar");
2960     g_variant_builder_add (&builder, "o", "/baz");
2961     value = g_variant_new("(ao^ao^a&o)", &builder, strvector, strvector);
2962     g_variant_iter_init (&tuple, value);
2963     g_variant_iter_next (&tuple, "ao", &array);
2964
2965     i = 0;
2966     while (g_variant_iter_loop (array, "o", &str))
2967       g_assert_cmpstr (str, ==, test_strs[i++]);
2968     g_assert (i == 3);
2969
2970     g_variant_iter_free (array);
2971
2972     /* start over */
2973     g_variant_iter_init (&tuple, value);
2974     g_variant_iter_next (&tuple, "ao", &array);
2975
2976     i = 0;
2977     while (g_variant_iter_loop (array, "&o", &str))
2978       g_assert_cmpstr (str, ==, test_strs[i++]);
2979     g_assert (i == 3);
2980
2981     g_variant_iter_free (array);
2982
2983     g_variant_iter_next (&tuple, "^a&o", &strv);
2984     g_variant_iter_next (&tuple, "^ao", &my_strv);
2985
2986     g_assert_cmpstr (strv[0], ==, "/hello");
2987     g_assert_cmpstr (strv[1], ==, "/world");
2988     g_assert (strv[2] == NULL);
2989     g_assert_cmpstr (my_strv[0], ==, "/hello");
2990     g_assert_cmpstr (my_strv[1], ==, "/world");
2991     g_assert (my_strv[2] == NULL);
2992
2993     g_variant_unref (value);
2994     g_strfreev (my_strv);
2995     g_free (strv);
2996   }
2997
2998   {
2999     const gchar *strvector[] = { "i", "ii", "iii", "iv", "v", "vi", NULL };
3000     GVariantBuilder builder;
3001     GVariantIter iter;
3002     GVariantIter *i2;
3003     GVariantIter *i3;
3004     GVariant *value;
3005     GVariant *sub;
3006     gchar **strv;
3007     gint i;
3008
3009     g_variant_builder_init (&builder, G_VARIANT_TYPE ("aag"));
3010     g_variant_builder_open (&builder, G_VARIANT_TYPE ("ag"));
3011     for (i = 0; i < 6; i++)
3012       if (i & 1)
3013         g_variant_builder_add (&builder, "g", strvector[i]);
3014       else
3015         g_variant_builder_add (&builder, "&g", strvector[i]);
3016     g_variant_builder_close (&builder);
3017     g_variant_builder_add (&builder, "^ag", strvector);
3018     g_variant_builder_add (&builder, "^ag", strvector);
3019     value = g_variant_new ("aag", &builder);
3020
3021     g_variant_iter_init (&iter, value);
3022     while (g_variant_iter_loop (&iter, "^ag", &strv))
3023       for (i = 0; i < 6; i++)
3024         g_assert_cmpstr (strv[i], ==, strvector[i]);
3025
3026     g_variant_iter_init (&iter, value);
3027     while (g_variant_iter_loop (&iter, "^a&g", &strv))
3028       for (i = 0; i < 6; i++)
3029         g_assert_cmpstr (strv[i], ==, strvector[i]);
3030
3031     g_variant_iter_init (&iter, value);
3032     while (g_variant_iter_loop (&iter, "ag", &i2))
3033       {
3034         gchar *str;
3035
3036         i = 0;
3037         while (g_variant_iter_loop (i2, "g", &str))
3038           g_assert_cmpstr (str, ==, strvector[i++]);
3039         g_assert (i == 6);
3040       }
3041
3042     g_variant_iter_init (&iter, value);
3043     i3 = g_variant_iter_copy (&iter);
3044     while (g_variant_iter_loop (&iter, "@ag", &sub))
3045       {
3046         gchar *str = g_variant_print (sub, TRUE);
3047         g_assert_cmpstr (str, ==,
3048                          "[signature 'i', 'ii', 'iii', 'iv', 'v', 'vi']");
3049         g_free (str);
3050       }
3051
3052   if (do_failed_test ("*NULL has already been returned*"))
3053     {
3054       g_variant_iter_next_value (&iter);
3055       abort ();
3056     }
3057
3058
3059     while (g_variant_iter_loop (i3, "*", &sub))
3060       {
3061         gchar *str = g_variant_print (sub, TRUE);
3062         g_assert_cmpstr (str, ==,
3063                          "[signature 'i', 'ii', 'iii', 'iv', 'v', 'vi']");
3064         g_free (str);
3065       }
3066
3067     g_variant_iter_free (i3);
3068
3069     for (i = 0; i < g_variant_n_children (value); i++)
3070       {
3071         gint j;
3072
3073         g_variant_get_child (value, i, "*", &sub);
3074
3075         for (j = 0; j < g_variant_n_children (sub); j++)
3076           {
3077             const gchar *str = NULL;
3078             GVariant *cval;
3079
3080             g_variant_get_child (sub, j, "&g", &str);
3081             g_assert_cmpstr (str, ==, strvector[j]);
3082
3083             cval = g_variant_get_child_value (sub, j);
3084             g_variant_get (cval, "&g", &str);
3085             g_assert_cmpstr (str, ==, strvector[j]);
3086             g_variant_unref (cval);
3087           }
3088
3089         g_variant_unref (sub);
3090       }
3091
3092     g_variant_unref (value);
3093   }
3094
3095   {
3096     gboolean justs[10];
3097     GVariant *value;
3098
3099     GVariant *vval;
3100     guchar byteval;
3101     gboolean bval;
3102     gint16 i16val;
3103     guint16 u16val;
3104     gint32 i32val;
3105     guint32 u32val;
3106     gint64 i64val;
3107     guint64 u64val;
3108     gdouble dval;
3109     gint32 hval;
3110
3111     /* test all 'nothing' */
3112     value = g_variant_new ("(mymbmnmqmimumxmtmhmdmv)",
3113                            FALSE, 'a',
3114                            FALSE, TRUE,
3115                            FALSE, (gint16) 123,
3116                            FALSE, (guint16) 123,
3117                            FALSE, (gint32) 123,
3118                            FALSE, (guint32) 123,
3119                            FALSE, (gint64) 123,
3120                            FALSE, (guint64) 123,
3121                            FALSE, (gint32) -1,
3122                            FALSE, (gdouble) 37.5,
3123                            NULL);
3124
3125     /* both NULL */
3126     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3127                    NULL, NULL,
3128                    NULL, NULL,
3129                    NULL, NULL,
3130                    NULL, NULL,
3131                    NULL, NULL,
3132                    NULL, NULL,
3133                    NULL, NULL,
3134                    NULL, NULL,
3135                    NULL, NULL,
3136                    NULL, NULL,
3137                    NULL);
3138
3139     /* NULL values */
3140     memset (justs, 1, sizeof justs);
3141     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3142                    &justs[0], NULL,
3143                    &justs[1], NULL,
3144                    &justs[2], NULL,
3145                    &justs[3], NULL,
3146                    &justs[4], NULL,
3147                    &justs[5], NULL,
3148                    &justs[6], NULL,
3149                    &justs[7], NULL,
3150                    &justs[8], NULL,
3151                    &justs[9], NULL,
3152                    NULL);
3153     g_assert (!(justs[0] || justs[1] || justs[2] || justs[3] || justs[4] ||
3154                 justs[5] || justs[6] || justs[7] || justs[8] || justs[9]));
3155
3156     /* both non-NULL */
3157     memset (justs, 1, sizeof justs);
3158     byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3159     vval = (void *) 1;
3160     bval = TRUE;
3161     dval = 88.88;
3162     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3163                    &justs[0], &byteval,
3164                    &justs[1], &bval,
3165                    &justs[2], &i16val,
3166                    &justs[3], &u16val,
3167                    &justs[4], &i32val,
3168                    &justs[5], &u32val,
3169                    &justs[6], &i64val,
3170                    &justs[7], &u64val,
3171                    &justs[8], &hval,
3172                    &justs[9], &dval,
3173                    &vval);
3174     g_assert (!(justs[0] || justs[1] || justs[2] || justs[3] || justs[4] ||
3175                 justs[5] || justs[6] || justs[7] || justs[8] || justs[9]));
3176     g_assert (byteval == '\0' && bval == FALSE);
3177     g_assert (i16val == 0 && u16val == 0 && i32val == 0 &&
3178               u32val == 0 && i64val == 0 && u64val == 0 &&
3179               hval == 0 && dval == 0.0);
3180     g_assert (vval == NULL);
3181
3182     /* NULL justs */
3183     byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3184     vval = (void *) 1;
3185     bval = TRUE;
3186     dval = 88.88;
3187     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3188                    NULL, &byteval,
3189                    NULL, &bval,
3190                    NULL, &i16val,
3191                    NULL, &u16val,
3192                    NULL, &i32val,
3193                    NULL, &u32val,
3194                    NULL, &i64val,
3195                    NULL, &u64val,
3196                    NULL, &hval,
3197                    NULL, &dval,
3198                    &vval);
3199     g_assert (byteval == '\0' && bval == FALSE);
3200     g_assert (i16val == 0 && u16val == 0 && i32val == 0 &&
3201               u32val == 0 && i64val == 0 && u64val == 0 &&
3202               hval == 0 && dval == 0.0);
3203     g_assert (vval == NULL);
3204
3205     g_variant_unref (value);
3206
3207
3208     /* test all 'just' */
3209     value = g_variant_new ("(mymbmnmqmimumxmtmhmdmv)",
3210                            TRUE, 'a',
3211                            TRUE, TRUE,
3212                            TRUE, (gint16) 123,
3213                            TRUE, (guint16) 123,
3214                            TRUE, (gint32) 123,
3215                            TRUE, (guint32) 123,
3216                            TRUE, (gint64) 123,
3217                            TRUE, (guint64) 123,
3218                            TRUE, (gint32) -1,
3219                            TRUE, (gdouble) 37.5,
3220                            g_variant_new ("()"));
3221
3222     /* both NULL */
3223     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3224                    NULL, NULL,
3225                    NULL, NULL,
3226                    NULL, NULL,
3227                    NULL, NULL,
3228                    NULL, NULL,
3229                    NULL, NULL,
3230                    NULL, NULL,
3231                    NULL, NULL,
3232                    NULL, NULL,
3233                    NULL, NULL,
3234                    NULL);
3235
3236     /* NULL values */
3237     memset (justs, 0, sizeof justs);
3238     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3239                    &justs[0], NULL,
3240                    &justs[1], NULL,
3241                    &justs[2], NULL,
3242                    &justs[3], NULL,
3243                    &justs[4], NULL,
3244                    &justs[5], NULL,
3245                    &justs[6], NULL,
3246                    &justs[7], NULL,
3247                    &justs[8], NULL,
3248                    &justs[9], NULL,
3249                    NULL);
3250     g_assert (justs[0] && justs[1] && justs[2] && justs[3] && justs[4] &&
3251               justs[5] && justs[6] && justs[7] && justs[8] && justs[9]);
3252
3253     /* both non-NULL */
3254     memset (justs, 0, sizeof justs);
3255     byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3256     vval = (void *) 1;
3257     bval = FALSE;
3258     dval = 88.88;
3259     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3260                    &justs[0], &byteval,
3261                    &justs[1], &bval,
3262                    &justs[2], &i16val,
3263                    &justs[3], &u16val,
3264                    &justs[4], &i32val,
3265                    &justs[5], &u32val,
3266                    &justs[6], &i64val,
3267                    &justs[7], &u64val,
3268                    &justs[8], &hval,
3269                    &justs[9], &dval,
3270                    &vval);
3271     g_assert (justs[0] && justs[1] && justs[2] && justs[3] && justs[4] &&
3272               justs[5] && justs[6] && justs[7] && justs[8] && justs[9]);
3273     g_assert (byteval == 'a' && bval == TRUE);
3274     g_assert (i16val == 123 && u16val == 123 && i32val == 123 &&
3275               u32val == 123 && i64val == 123 && u64val == 123 &&
3276               hval == -1 && dval == 37.5);
3277     g_assert (g_variant_is_of_type (vval, G_VARIANT_TYPE_UNIT));
3278     g_variant_unref (vval);
3279
3280     /* NULL justs */
3281     byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3282     vval = (void *) 1;
3283     bval = TRUE;
3284     dval = 88.88;
3285     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3286                    NULL, &byteval,
3287                    NULL, &bval,
3288                    NULL, &i16val,
3289                    NULL, &u16val,
3290                    NULL, &i32val,
3291                    NULL, &u32val,
3292                    NULL, &i64val,
3293                    NULL, &u64val,
3294                    NULL, &hval,
3295                    NULL, &dval,
3296                    &vval);
3297     g_assert (byteval == 'a' && bval == TRUE);
3298     g_assert (i16val == 123 && u16val == 123 && i32val == 123 &&
3299               u32val == 123 && i64val == 123 && u64val == 123 &&
3300               hval == -1 && dval == 37.5);
3301     g_assert (g_variant_is_of_type (vval, G_VARIANT_TYPE_UNIT));
3302     g_variant_unref (vval);
3303
3304     g_variant_unref (value);
3305   }
3306
3307   g_variant_type_info_assert_no_infos ();
3308 }
3309
3310 static void
3311 hash_get (GVariant    *value,
3312           const gchar *format,
3313           ...)
3314 {
3315   const gchar *endptr = NULL;
3316   gboolean hash;
3317   va_list ap;
3318
3319   hash = g_str_has_suffix (format, "#");
3320
3321   va_start (ap, format);
3322   g_variant_get_va (value, format, hash ? &endptr : NULL, &ap);
3323   va_end (ap);
3324
3325   if (hash)
3326     g_assert (*endptr == '#');
3327 }
3328
3329 static GVariant *
3330 hash_new (const gchar *format,
3331           ...)
3332 {
3333   const gchar *endptr = NULL;
3334   GVariant *value;
3335   gboolean hash;
3336   va_list ap;
3337
3338   hash = g_str_has_suffix (format, "#");
3339
3340   va_start (ap, format);
3341   value = g_variant_new_va (format, hash ? &endptr : NULL, &ap);
3342   va_end (ap);
3343
3344   if (hash)
3345     g_assert (*endptr == '#');
3346
3347   return value;
3348 }
3349
3350 static void
3351 test_valist (void)
3352 {
3353   GVariant *value;
3354   gint32 x;
3355
3356   x = 0;
3357   value = hash_new ("i", 234);
3358   hash_get (value, "i", &x);
3359   g_assert (x == 234);
3360   g_variant_unref (value);
3361
3362   x = 0;
3363   value = hash_new ("i#", 234);
3364   hash_get (value, "i#", &x);
3365   g_assert (x == 234);
3366   g_variant_unref (value);
3367
3368   g_variant_type_info_assert_no_infos ();
3369 }
3370
3371 static void
3372 test_builder_memory (void)
3373 {
3374   GVariantBuilder *hb;
3375   GVariantBuilder sb;
3376
3377   hb = g_variant_builder_new  (G_VARIANT_TYPE_ARRAY);
3378   g_variant_builder_open (hb, G_VARIANT_TYPE_ARRAY);
3379   g_variant_builder_open (hb, G_VARIANT_TYPE_ARRAY);
3380   g_variant_builder_open (hb, G_VARIANT_TYPE_ARRAY);
3381   g_variant_builder_add (hb, "s", "some value");
3382   g_variant_builder_ref (hb);
3383   g_variant_builder_unref (hb);
3384   g_variant_builder_unref (hb);
3385
3386   hb = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
3387   g_variant_builder_unref (hb);
3388
3389   hb = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
3390   g_variant_builder_clear (hb);
3391   g_variant_builder_unref (hb);
3392
3393   g_variant_builder_init (&sb, G_VARIANT_TYPE_ARRAY);
3394   g_variant_builder_open (&sb, G_VARIANT_TYPE_ARRAY);
3395   g_variant_builder_open (&sb, G_VARIANT_TYPE_ARRAY);
3396   g_variant_builder_add (&sb, "s", "some value");
3397   g_variant_builder_clear (&sb);
3398
3399   g_variant_type_info_assert_no_infos ();
3400 }
3401
3402 static void
3403 test_hashing (void)
3404 {
3405   GVariant *items[4096];
3406   GHashTable *table;
3407   gint i;
3408
3409   table = g_hash_table_new_full (g_variant_hash, g_variant_equal,
3410                                  (GDestroyNotify ) g_variant_unref,
3411                                  NULL);
3412
3413   for (i = 0; i < G_N_ELEMENTS (items); i++)
3414     {
3415       TreeInstance *tree;
3416       gint j;
3417
3418  again:
3419       tree = tree_instance_new (NULL, 0);
3420       items[i] = tree_instance_get_gvariant (tree);
3421       tree_instance_free (tree);
3422
3423       for (j = 0; j < i; j++)
3424         if (g_variant_equal (items[i], items[j]))
3425           {
3426             g_variant_unref (items[i]);
3427             goto again;
3428           }
3429
3430       g_hash_table_insert (table,
3431                            g_variant_ref_sink (items[i]),
3432                            GINT_TO_POINTER (i));
3433     }
3434
3435   for (i = 0; i < G_N_ELEMENTS (items); i++)
3436     {
3437       gpointer result;
3438
3439       result = g_hash_table_lookup (table, items[i]);
3440       g_assert_cmpint (GPOINTER_TO_INT (result), ==, i);
3441     }
3442
3443   g_hash_table_unref (table);
3444
3445   g_variant_type_info_assert_no_infos ();
3446 }
3447
3448 static void
3449 test_gv_byteswap ()
3450 {
3451 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
3452 # define native16(x)  x, 0
3453 # define swapped16(x) 0, x
3454 #else
3455 # define native16(x)  0, x
3456 # define swapped16(x) x, 0
3457 #endif
3458   /* all kinds of of crazy randomised testing already performed on the
3459    * byteswapper in the /gvariant/serialiser/byteswap test and all kinds
3460    * of crazy randomised testing performed against the serialiser
3461    * normalisation functions in the /gvariant/serialiser/fuzz/ tests.
3462    *
3463    * just test a few simple cases here to make sure they each work
3464    */
3465   guchar valid_data[] = { 'a', '\0', swapped16(66), 2,
3466                           0,
3467                           'b', '\0', swapped16(77), 2,
3468                           5, 11 };
3469   guchar corrupt_data[] = { 'a', '\0', swapped16(66), 2,
3470                             0,
3471                             'b', '\0', swapped16(77), 2,
3472                             6, 11 };
3473   GVariant *value, *swapped;
3474   gchar *string, *string2;
3475
3476
3477   /* trusted */
3478   value = g_variant_new_from_data (G_VARIANT_TYPE ("a(sn)"),
3479                                    valid_data, sizeof valid_data, TRUE,
3480                                    NULL, NULL);
3481   swapped = g_variant_byteswap (value);
3482   g_variant_unref (value);
3483   g_assert (g_variant_get_size (swapped) == 13);
3484   string = g_variant_print (swapped, FALSE);
3485   g_variant_unref (swapped);
3486   g_assert_cmpstr (string, ==, "[('a', 66), ('b', 77)]");
3487   g_free (string);
3488
3489   /* untrusted but valid */
3490   value = g_variant_new_from_data (G_VARIANT_TYPE ("a(sn)"),
3491                                    valid_data, sizeof valid_data, FALSE,
3492                                    NULL, NULL);
3493   swapped = g_variant_byteswap (value);
3494   g_variant_unref (value);
3495   g_assert (g_variant_get_size (swapped) == 13);
3496   string = g_variant_print (swapped, FALSE);
3497   g_variant_unref (swapped);
3498   g_assert_cmpstr (string, ==, "[('a', 66), ('b', 77)]");
3499   g_free (string);
3500
3501   /* untrusted, invalid */
3502   value = g_variant_new_from_data (G_VARIANT_TYPE ("a(sn)"),
3503                                    corrupt_data, sizeof corrupt_data, FALSE,
3504                                    NULL, NULL);
3505   string = g_variant_print (value, FALSE);
3506   swapped = g_variant_byteswap (value);
3507   g_variant_unref (value);
3508   g_assert (g_variant_get_size (swapped) == 13);
3509   value = g_variant_byteswap (swapped);
3510   g_variant_unref (swapped);
3511   string2 = g_variant_print (value, FALSE);
3512   g_assert (g_variant_get_size (value) == 13);
3513   g_variant_unref (value);
3514   g_assert_cmpstr (string, ==, string2);
3515   g_free (string2);
3516   g_free (string);
3517 }
3518
3519 static void
3520 test_parser (void)
3521 {
3522   TreeInstance *tree;
3523   GVariant *parsed;
3524   GVariant *value;
3525   gchar *pt, *p;
3526   gchar *res;
3527
3528   tree = tree_instance_new (NULL, 3);
3529   value = tree_instance_get_gvariant (tree);
3530   tree_instance_free (tree);
3531
3532   pt = g_variant_print (value, TRUE);
3533   p = g_variant_print (value, FALSE);
3534
3535   parsed = g_variant_parse (NULL, pt, NULL, NULL, NULL);
3536   res = g_variant_print (parsed, FALSE);
3537   g_assert_cmpstr (p, ==, res);
3538   g_variant_unref (parsed);
3539   g_free (res);
3540
3541   parsed = g_variant_parse (g_variant_get_type (value), p,
3542                             NULL, NULL, NULL);
3543   res = g_variant_print (parsed, TRUE);
3544   g_assert_cmpstr (pt, ==, res);
3545   g_variant_unref (parsed);
3546   g_free (res);
3547
3548   g_variant_unref (value);
3549   g_free (pt);
3550   g_free (p);
3551 }
3552
3553 static void
3554 test_parses (void)
3555 {
3556   gint i;
3557
3558   for (i = 0; i < 100; i++)
3559     {
3560       test_parser ();
3561     }
3562
3563   /* mini test */
3564   {
3565     gchar str[256];
3566     GVariant *val;
3567     gchar *p, *p2;
3568
3569     for (i = 0; i < 256; i++)
3570       str[i] = i + 1;
3571
3572     val = g_variant_new_string (str);
3573     p = g_variant_print (val, FALSE);
3574     g_variant_unref (val);
3575
3576     val = g_variant_parse (NULL, p, NULL, NULL, NULL);
3577     p2 = g_variant_print (val, FALSE);
3578
3579     g_assert_cmpstr (str, ==, g_variant_get_string (val, NULL));
3580     g_assert_cmpstr (p, ==, p2);
3581
3582     g_variant_unref (val);
3583     g_free (p2);
3584     g_free (p);
3585   }
3586
3587   /* another mini test */
3588   {
3589     const gchar *end;
3590     GVariant *value;
3591
3592     value = g_variant_parse (G_VARIANT_TYPE_INT32, "1 2 3", NULL, &end, NULL);
3593     g_assert_cmpint (g_variant_get_int32 (value), ==, 1);
3594     /* make sure endptr returning works */
3595     g_assert_cmpstr (end, ==, " 2 3");
3596     g_variant_unref (value);
3597   }
3598
3599   g_variant_type_info_assert_no_infos ();
3600 }
3601
3602 static void
3603 test_parse_failures (void)
3604 {
3605   const gchar *test[] = {
3606     "[1, 2,",                   "6:",              "expected value",
3607     "",                         "0:",              "expected value",
3608     "(1, 2,",                   "6:",              "expected value",
3609     "<1",                       "2:",              "expected `>'",
3610     "[]",                       "0-2:",            "unable to infer",
3611     "(,",                       "1:",              "expected value",
3612     "[4,'']",                   "1-2,3-5:",        "common type",
3613     "[4, '', 5]",               "1-2,4-6:",        "common type",
3614     "['', 4, 5]",               "1-3,5-6:",        "common type",
3615     "[4, 5, '']",               "1-2,7-9:",        "common type",
3616     "[[4], [], ['']]",          "1-4,10-14:",      "common type",
3617     "[[], [4], ['']]",          "5-8,10-14:",      "common type",
3618     "just",                     "4:",              "expected value",
3619     "nothing",                  "0-7:",            "unable to infer",
3620     "just [4, '']",             "6-7,9-11:",       "common type",
3621     "[[4,'']]",                 "2-3,4-6:",        "common type",
3622     "([4,''],)",                "2-3,4-6:",        "common type",
3623     "(4)",                      "2:",              "`,'",
3624     "{}",                       "0-2:",            "unable to infer",
3625     "{[1,2],[3,4]}",            "0-13:",           "basic types",
3626     "{[1,2]:[3,4]}",            "0-13:",           "basic types",
3627     "justt",                    "0-5:",            "unknown keyword",
3628     "nothng",                   "0-6:",            "unknown keyword",
3629     "uint33",                   "0-6:",            "unknown keyword",
3630     "@mi just ''",              "9-11:",           "can not parse as",
3631     "@ai ['']",                 "5-7:",            "can not parse as",
3632     "@(i) ('',)",               "6-8:",            "can not parse as",
3633     "[[], 5]",                  "1-3,5-6:",        "common type",
3634     "[[5], 5]",                 "1-4,6-7:",        "common type",
3635     "5 5",                      "2:",              "expected end of input",
3636     "[5, [5, '']]",             "5-6,8-10:",       "common type",
3637     "@i just 5",                "3-9:",            "can not parse as",
3638     "@i nothing",               "3-10:",           "can not parse as",
3639     "@i []",                    "3-5:",            "can not parse as",
3640     "@i ()",                    "3-5:",            "can not parse as",
3641     "@ai (4,)",                 "4-8:",            "can not parse as",
3642     "@(i) []",                  "5-7:",            "can not parse as",
3643     "(5 5)",                    "3:",              "expected `,'",
3644     "[5 5]",                    "3:",              "expected `,' or `]'",
3645     "(5, 5 5)",                 "6:",              "expected `,' or `)'",
3646     "[5, 5 5]",                 "6:",              "expected `,' or `]'",
3647     "<@i []>",                  "4-6:",            "can not parse as",
3648     "<[5 5]>",                  "4:",              "expected `,' or `]'",
3649     "{[4,''],5}",               "2-3,4-6:",        "common type",
3650     "{5,[4,'']}",               "4-5,6-8:",        "common type",
3651     "@i {1,2}",                 "3-8:",            "can not parse as",
3652     "{@i '', 5}",               "4-6:",            "can not parse as",
3653     "{5, @i ''}",               "7-9:",            "can not parse as",
3654     "@ai {}",                   "4-6:",            "can not parse as",
3655     "{@i '': 5}",               "4-6:",            "can not parse as",
3656     "{5: @i ''}",               "7-9:",            "can not parse as",
3657     "{<4,5}",                   "3:",              "expected `>'",
3658     "{4,<5}",                   "5:",              "expected `>'",
3659     "{4,5,6}",                  "4:",              "expected `}'",
3660     "{5 5}",                    "3:",              "expected `:' or `,'",
3661     "{4: 5: 6}",                "5:",              "expected `,' or `}'",
3662     "{4:5,<6:7}",               "7:",              "expected `>'",
3663     "{4:5,6:<7}",               "9:",              "expected `>'",
3664     "{4:5,6 7}",                "7:",              "expected `:'",
3665     "@o 'foo'",                 "3-8:",            "object path",
3666     "@g 'zzz'",                 "3-8:",            "signature",
3667     "@i true",                  "3-7:",            "can not parse as",
3668     "@z 4",                     "0-2:",            "invalid type",
3669     "@a* []",                   "0-3:",            "definite",
3670     "@ai [3 3]",                "7:",              "expected `,' or `]'",
3671     "18446744073709551616",     "0-20:",           "too big for any type",
3672     "-18446744073709551616",    "0-21:",           "too big for any type",
3673     "byte 256",                 "5-8:",            "out of range for type",
3674     "byte -1",                  "5-7:",            "out of range for type",
3675     "int16 32768",              "6-11:",           "out of range for type",
3676     "int16 -32769",             "6-12:",           "out of range for type",
3677     "uint16 -1",                "7-9:",            "out of range for type",
3678     "uint16 65536",             "7-12:",           "out of range for type",
3679     "2147483648",               "0-10:",           "out of range for type",
3680     "-2147483649",              "0-11:",           "out of range for type",
3681     "uint32 -1",                "7-9:",            "out of range for type",
3682     "uint32 4294967296",        "7-17:",           "out of range for type",
3683     "@x 9223372036854775808",   "3-22:",           "out of range for type",
3684     "@x -9223372036854775809",  "3-23:",           "out of range for type",
3685     "@t -1",                    "3-5:",            "out of range for type",
3686     "@t 18446744073709551616",  "3-23:",           "too big for any type",
3687     "handle 2147483648",        "7-17:",           "out of range for type",
3688     "handle -2147483649",       "7-18:",           "out of range for type",
3689     "1.798e308",                "0-9:",            "too big for any type",
3690     "37.5a488",                 "4-5:",            "invalid character",
3691     "0x7ffgf",                  "5-6:",            "invalid character",
3692     "07758",                    "4-5:",            "invalid character",
3693     "123a5",                    "3-4:",            "invalid character",
3694     "@ai 123",                  "4-7:",            "can not parse as",
3695     "'\"\\'",                   "0-4:",            "unterminated string",
3696     "'\"\\'\\",                 "0-5:",            "unterminated string",
3697     "boolean 4",                "8-9:",            "can not parse as",
3698     "int32 true",               "6-10:",           "can not parse as",
3699     "[double 5, int32 5]",      "1-9,11-18:",      "common type",
3700     "string 4",                 "7-8:",            "can not parse as"
3701   };
3702   gint i;
3703
3704   for (i = 0; i < G_N_ELEMENTS (test); i += 3)
3705     {
3706       GError *error = NULL;
3707       GVariant *value;
3708
3709       value = g_variant_parse (NULL, test[i], NULL, NULL, &error);
3710       g_assert (value == NULL);
3711
3712       if (!strstr (error->message, test[i+2]))
3713         g_error ("test %d: Can't find `%s' in `%s'", i / 3,
3714                  test[i+2], error->message);
3715
3716       if (!g_str_has_prefix (error->message, test[i+1]))
3717         g_error ("test %d: Expected location `%s' in `%s'", i / 3,
3718                  test[i+1], error->message);
3719
3720       g_error_free (error);
3721     }
3722 }
3723
3724 static void
3725 test_parse_positional (void)
3726 {
3727   GVariant *value;
3728   check_and_free (g_variant_new_parsed ("[('one', 1), (%s, 2),"
3729                                         " ('three', %i)]", "two", 3),
3730                   "[('one', 1), ('two', 2), ('three', 3)]");
3731   value = g_variant_new_parsed ("[('one', 1), (%s, 2),"
3732                                 " ('three', %u)]", "two", 3);
3733   g_assert (g_variant_is_of_type (value, G_VARIANT_TYPE ("a(su)")));
3734   check_and_free (value, "[('one', 1), ('two', 2), ('three', 3)]");
3735   check_and_free (g_variant_new_parsed ("{%s:%i}", "one", 1), "{'one': 1}");
3736
3737   if (do_failed_test ("*GVariant format string*"))
3738     {
3739       g_variant_new_parsed ("%z");
3740       abort ();
3741     }
3742
3743   if (do_failed_test ("*can not parse as*"))
3744     {
3745       g_variant_new_parsed ("uint32 %i", 2);
3746       abort ();
3747     }
3748
3749   if (do_failed_test ("*expected GVariant of type `i'*"))
3750     {
3751       g_variant_new_parsed ("%@i", g_variant_new_uint32 (2));
3752       abort ();
3753     }
3754 }
3755
3756 int
3757 main (int argc, char **argv)
3758 {
3759   gint i;
3760
3761   g_test_init (&argc, &argv, NULL);
3762
3763   g_test_add_func ("/gvariant/type", test_gvarianttype);
3764   g_test_add_func ("/gvariant/typeinfo", test_gvarianttypeinfo);
3765   g_test_add_func ("/gvariant/serialiser/maybe", test_maybes);
3766   g_test_add_func ("/gvariant/serialiser/array", test_arrays);
3767   g_test_add_func ("/gvariant/serialiser/tuple", test_tuples);
3768   g_test_add_func ("/gvariant/serialiser/variant", test_variants);
3769   g_test_add_func ("/gvariant/serialiser/strings", test_strings);
3770   g_test_add_func ("/gvariant/serialiser/byteswap", test_byteswaps);
3771
3772   for (i = 1; i <= 20; i += 4)
3773     {
3774       char *testname;
3775
3776       testname = g_strdup_printf ("/gvariant/serialiser/fuzz/%d%%", i);
3777       g_test_add_data_func (testname, GINT_TO_POINTER (i),
3778                             (gpointer) test_fuzzes);
3779       g_free (testname);
3780     }
3781
3782   g_test_add_func ("/gvariant/utf8", test_utf8);
3783   g_test_add_func ("/gvariant/containers", test_containers);
3784   g_test_add_func ("/gvariant/format-strings", test_format_strings);
3785   g_test_add_func ("/gvariant/invalid-varargs", test_invalid_varargs);
3786   g_test_add_func ("/gvariant/varargs", test_varargs);
3787   g_test_add_func ("/gvariant/valist", test_valist);
3788   g_test_add_func ("/gvariant/builder-memory", test_builder_memory);
3789   g_test_add_func ("/gvariant/hashing", test_hashing);
3790   g_test_add_func ("/gvariant/byteswap", test_gv_byteswap);
3791   g_test_add_func ("/gvariant/parser", test_parses);
3792   g_test_add_func ("/gvariant/parse-failures", test_parse_failures);
3793   g_test_add_func ("/gvariant/parse-positional", test_parse_positional);
3794
3795   return g_test_run ();
3796 }