GVariant: deal with non-8-aligned malloc()
[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   g_free (((gchar *) data) - flavour);
1273 }
1274
1275 static void
1276 append_offset (guchar **offset_ptr,
1277                gsize    offset,
1278                guint    offset_size)
1279 {
1280   union
1281   {
1282     guchar bytes[sizeof (gsize)];
1283     gsize integer;
1284   } tmpvalue;
1285
1286   tmpvalue.integer = GSIZE_TO_LE (offset);
1287   memcpy (*offset_ptr, tmpvalue.bytes, offset_size);
1288   *offset_ptr += offset_size;
1289 }
1290
1291 static void
1292 prepend_offset (guchar **offset_ptr,
1293                 gsize    offset,
1294                 guint    offset_size)
1295 {
1296   union
1297   {
1298     guchar bytes[sizeof (gsize)];
1299     gsize integer;
1300   } tmpvalue;
1301
1302   *offset_ptr -= offset_size;
1303   tmpvalue.integer = GSIZE_TO_LE (offset);
1304   memcpy (*offset_ptr, tmpvalue.bytes, offset_size);
1305 }
1306
1307 static void
1308 test_maybe (void)
1309 {
1310   GVariantTypeInfo *type_info;
1311   RandomInstance *instance;
1312   gsize needed_size;
1313   guchar *data;
1314
1315   instance = random_instance (NULL);
1316
1317   {
1318     const gchar *element;
1319     gchar *tmp;
1320
1321     element = g_variant_type_info_get_type_string (instance->type_info);
1322     tmp = g_strdup_printf ("m%s", element);
1323     type_info = g_variant_type_info_get (G_VARIANT_TYPE (tmp));
1324     g_free (tmp);
1325   }
1326
1327   needed_size = g_variant_serialiser_needed_size (type_info,
1328                                                   random_instance_filler,
1329                                                   NULL, 0);
1330   g_assert_cmpint (needed_size, ==, 0);
1331
1332   needed_size = g_variant_serialiser_needed_size (type_info,
1333                                                   random_instance_filler,
1334                                                   (gpointer *) &instance, 1);
1335
1336   if (instance->is_fixed_sized)
1337     g_assert_cmpint (needed_size, ==, instance->size);
1338   else
1339     g_assert_cmpint (needed_size, ==, instance->size + 1);
1340
1341   {
1342     guchar *ptr;
1343
1344     ptr = data = g_malloc (needed_size);
1345     append_instance_data (instance, &ptr);
1346
1347     if (!instance->is_fixed_sized)
1348       *ptr++ = '\0';
1349
1350     g_assert_cmpint (ptr - data, ==, needed_size);
1351   }
1352
1353   {
1354     guint alignment;
1355     guint flavour;
1356
1357     alignment = (instance->alignment & ALIGN_BITS) + 1;
1358
1359     for (flavour = 0; flavour < 8; flavour += alignment)
1360       {
1361         GVariantSerialised serialised;
1362         GVariantSerialised child;
1363
1364         serialised.type_info = type_info;
1365         serialised.data = flavoured_malloc (needed_size, flavour);
1366         serialised.size = needed_size;
1367
1368         g_variant_serialiser_serialise (serialised,
1369                                         random_instance_filler,
1370                                         (gpointer *) &instance, 1);
1371         child = g_variant_serialised_get_child (serialised, 0);
1372         g_assert (child.type_info == instance->type_info);
1373         random_instance_assert (instance, child.data, child.size);
1374         g_variant_type_info_unref (child.type_info);
1375         flavoured_free (serialised.data, flavour);
1376       }
1377   }
1378
1379   g_variant_type_info_unref (type_info);
1380   random_instance_free (instance);
1381   g_free (data);
1382 }
1383
1384 static void
1385 test_maybes (void)
1386 {
1387   guint i;
1388
1389   for (i = 0; i < 1000; i++)
1390     test_maybe ();
1391
1392   g_variant_type_info_assert_no_infos ();
1393 }
1394
1395 static void
1396 test_array (void)
1397 {
1398   GVariantTypeInfo *element_info;
1399   GVariantTypeInfo *array_info;
1400   RandomInstance **instances;
1401   gsize needed_size;
1402   gsize offset_size;
1403   guint n_children;
1404   guchar *data;
1405
1406   {
1407     gchar *element_type, *array_type;
1408
1409     element_type = random_type_string ();
1410     array_type = g_strdup_printf ("a%s", element_type);
1411
1412     element_info = g_variant_type_info_get (G_VARIANT_TYPE (element_type));
1413     array_info = g_variant_type_info_get (G_VARIANT_TYPE (array_type));
1414     g_assert (g_variant_type_info_element (array_info) == element_info);
1415
1416     g_free (element_type);
1417     g_free (array_type);
1418   }
1419
1420   {
1421     guint i;
1422
1423     n_children = g_test_rand_int_range (0, MAX_ARRAY_CHILDREN);
1424     instances = g_new (RandomInstance *, n_children);
1425     for (i = 0; i < n_children; i++)
1426       instances[i] = random_instance (element_info);
1427   }
1428
1429   needed_size = g_variant_serialiser_needed_size (array_info,
1430                                                   random_instance_filler,
1431                                                   (gpointer *) instances,
1432                                                   n_children);
1433
1434   {
1435     gsize element_fixed_size;
1436     gsize body_size = 0;
1437     guint i;
1438
1439     for (i = 0; i < n_children; i++)
1440       append_instance_size (instances[i], &body_size);
1441
1442     g_variant_type_info_query (element_info, NULL, &element_fixed_size);
1443
1444     if (!element_fixed_size)
1445       {
1446         offset_size = calculate_offset_size (body_size, n_children);
1447
1448         if (offset_size == 0)
1449           offset_size = 1;
1450       }
1451     else
1452       offset_size = 0;
1453
1454     g_assert_cmpint (needed_size, ==, body_size + n_children * offset_size);
1455   }
1456
1457   {
1458     guchar *offset_ptr, *body_ptr;
1459     guint i;
1460
1461     body_ptr = data = g_malloc (needed_size);
1462     offset_ptr = body_ptr + needed_size - offset_size * n_children;
1463
1464     for (i = 0; i < n_children; i++)
1465       {
1466         append_instance_data (instances[i], &body_ptr);
1467         append_offset (&offset_ptr, body_ptr - data, offset_size);
1468       }
1469
1470     g_assert (body_ptr == data + needed_size - offset_size * n_children);
1471     g_assert (offset_ptr == data + needed_size);
1472   }
1473
1474   {
1475     guint alignment;
1476     gsize flavour;
1477     guint i;
1478
1479     g_variant_type_info_query (array_info, &alignment, NULL);
1480     alignment = (alignment & ALIGN_BITS) + 1;
1481
1482     for (flavour = 0; flavour < 8; flavour += alignment)
1483       {
1484         GVariantSerialised serialised;
1485
1486         serialised.type_info = array_info;
1487         serialised.data = flavoured_malloc (needed_size, flavour);
1488         serialised.size = needed_size;
1489
1490         g_variant_serialiser_serialise (serialised, random_instance_filler,
1491                                         (gpointer *) instances, n_children);
1492
1493         g_assert (memcmp (serialised.data, data, serialised.size) == 0);
1494         g_assert (g_variant_serialised_n_children (serialised) == n_children);
1495
1496         for (i = 0; i < n_children; i++)
1497           {
1498             GVariantSerialised child;
1499
1500             child = g_variant_serialised_get_child (serialised, i);
1501             g_assert (child.type_info == instances[i]->type_info);
1502             random_instance_assert (instances[i], child.data, child.size);
1503             g_variant_type_info_unref (child.type_info);
1504           }
1505
1506         flavoured_free (serialised.data, flavour);
1507       }
1508   }
1509
1510   {
1511     guint i;
1512
1513     for (i = 0; i < n_children; i++)
1514       random_instance_free (instances[i]);
1515     g_free (instances);
1516   }
1517
1518   g_variant_type_info_unref (element_info);
1519   g_variant_type_info_unref (array_info);
1520   g_free (data);
1521 }
1522
1523 static void
1524 test_arrays (void)
1525 {
1526   guint i;
1527
1528   for (i = 0; i < 100; i++)
1529     test_array ();
1530
1531   g_variant_type_info_assert_no_infos ();
1532 }
1533
1534 static void
1535 test_tuple (void)
1536 {
1537   GVariantTypeInfo *type_info;
1538   RandomInstance **instances;
1539   gboolean fixed_size;
1540   gsize needed_size;
1541   gsize offset_size;
1542   guint n_children;
1543   guint alignment;
1544   guchar *data;
1545
1546   n_children = g_test_rand_int_range (0, MAX_TUPLE_CHILDREN);
1547   instances = g_new (RandomInstance *, n_children);
1548
1549   {
1550     GString *type_string;
1551     guint i;
1552
1553     fixed_size = TRUE;
1554     alignment = 0;
1555
1556     type_string = g_string_new ("(");
1557     for (i = 0; i < n_children; i++)
1558       {
1559         const gchar *str;
1560
1561         instances[i] = random_instance (NULL);
1562
1563         alignment |= instances[i]->alignment;
1564         if (!instances[i]->is_fixed_sized)
1565           fixed_size = FALSE;
1566
1567         str = g_variant_type_info_get_type_string (instances[i]->type_info);
1568         g_string_append (type_string, str);
1569       }
1570     g_string_append_c (type_string, ')');
1571
1572     type_info = g_variant_type_info_get (G_VARIANT_TYPE (type_string->str));
1573     g_string_free (type_string, TRUE);
1574   }
1575
1576   needed_size = g_variant_serialiser_needed_size (type_info,
1577                                                   random_instance_filler,
1578                                                   (gpointer *) instances,
1579                                                   n_children);
1580   {
1581     gsize body_size = 0;
1582     gsize offsets = 0;
1583     guint i;
1584
1585     for (i = 0; i < n_children; i++)
1586       {
1587         append_instance_size (instances[i], &body_size);
1588
1589         if (i != n_children - 1 && !instances[i]->is_fixed_sized)
1590           offsets++;
1591       }
1592
1593     if (fixed_size)
1594       {
1595         body_size += (-body_size) & alignment;
1596
1597         g_assert ((body_size == 0) == (n_children == 0));
1598         if (n_children == 0)
1599           body_size = 1;
1600       }
1601
1602     offset_size = calculate_offset_size (body_size, offsets);
1603     g_assert_cmpint (needed_size, ==, body_size + offsets * offset_size);
1604   }
1605
1606   {
1607     guchar *body_ptr;
1608     guchar *ofs_ptr;
1609     guint i;
1610
1611     body_ptr = data = g_malloc (needed_size);
1612     ofs_ptr = body_ptr + needed_size;
1613
1614     for (i = 0; i < n_children; i++)
1615       {
1616         append_instance_data (instances[i], &body_ptr);
1617
1618         if (i != n_children - 1 && !instances[i]->is_fixed_sized)
1619           prepend_offset (&ofs_ptr, body_ptr - data, offset_size);
1620       }
1621
1622     if (fixed_size)
1623       {
1624         while (((gsize) body_ptr) & alignment)
1625           *body_ptr++ = '\0';
1626
1627         g_assert ((body_ptr == data) == (n_children == 0));
1628         if (n_children == 0)
1629           *body_ptr++ = '\0';
1630
1631       }
1632
1633
1634     g_assert (body_ptr == ofs_ptr);
1635   }
1636
1637   {
1638     gsize flavour;
1639     guint i;
1640
1641     alignment = (alignment & ALIGN_BITS) + 1;
1642
1643     for (flavour = 0; flavour < 8; flavour += alignment)
1644       {
1645         GVariantSerialised serialised;
1646
1647         serialised.type_info = type_info;
1648         serialised.data = flavoured_malloc (needed_size, flavour);
1649         serialised.size = needed_size;
1650
1651         g_variant_serialiser_serialise (serialised, random_instance_filler,
1652                                         (gpointer *) instances, n_children);
1653
1654         g_assert (memcmp (serialised.data, data, serialised.size) == 0);
1655         g_assert (g_variant_serialised_n_children (serialised) == n_children);
1656
1657         for (i = 0; i < n_children; i++)
1658           {
1659             GVariantSerialised child;
1660
1661             child = g_variant_serialised_get_child (serialised, i);
1662             g_assert (child.type_info == instances[i]->type_info);
1663             random_instance_assert (instances[i], child.data, child.size);
1664             g_variant_type_info_unref (child.type_info);
1665           }
1666
1667         flavoured_free (serialised.data, flavour);
1668       }
1669   }
1670
1671   {
1672     guint i;
1673
1674     for (i = 0; i < n_children; i++)
1675       random_instance_free (instances[i]);
1676     g_free (instances);
1677   }
1678
1679   g_variant_type_info_unref (type_info);
1680   g_free (data);
1681 }
1682
1683 static void
1684 test_tuples (void)
1685 {
1686   guint i;
1687
1688   for (i = 0; i < 100; i++)
1689     test_tuple ();
1690
1691   g_variant_type_info_assert_no_infos ();
1692 }
1693
1694 static void
1695 test_variant (void)
1696 {
1697   GVariantTypeInfo *type_info;
1698   RandomInstance *instance;
1699   const gchar *type_string;
1700   gsize needed_size;
1701   guchar *data;
1702   gsize len;
1703
1704   type_info = g_variant_type_info_get (G_VARIANT_TYPE_VARIANT);
1705   instance = random_instance (NULL);
1706
1707   type_string = g_variant_type_info_get_type_string (instance->type_info);
1708   len = strlen (type_string);
1709
1710   needed_size = g_variant_serialiser_needed_size (type_info,
1711                                                   random_instance_filler,
1712                                                   (gpointer *) &instance, 1);
1713
1714   g_assert_cmpint (needed_size, ==, instance->size + 1 + len);
1715
1716   {
1717     guchar *ptr;
1718
1719     ptr = data = g_malloc (needed_size);
1720     append_instance_data (instance, &ptr);
1721     *ptr++ = '\0';
1722     memcpy (ptr, type_string, len);
1723     ptr += len;
1724
1725     g_assert (data + needed_size == ptr);
1726   }
1727
1728   {
1729     gsize alignment;
1730     gsize flavour;
1731
1732     /* variants are always 8-aligned */
1733     alignment = ALIGN_BITS + 1;
1734
1735     for (flavour = 0; flavour < 8; flavour += alignment)
1736       {
1737         GVariantSerialised serialised;
1738         GVariantSerialised child;
1739
1740         serialised.type_info = type_info;
1741         serialised.data = flavoured_malloc (needed_size, flavour);
1742         serialised.size = needed_size;
1743
1744         g_variant_serialiser_serialise (serialised, random_instance_filler,
1745                                         (gpointer *) &instance, 1);
1746
1747         g_assert (memcmp (serialised.data, data, serialised.size) == 0);
1748         g_assert (g_variant_serialised_n_children (serialised) == 1);
1749
1750         child = g_variant_serialised_get_child (serialised, 0);
1751         g_assert (child.type_info == instance->type_info);
1752         random_instance_check (instance, child.data, child.size);
1753
1754         g_variant_type_info_unref (child.type_info);
1755         flavoured_free (serialised.data, flavour);
1756       }
1757   }
1758
1759   g_variant_type_info_unref (type_info);
1760   random_instance_free (instance);
1761   g_free (data);
1762 }
1763
1764 static void
1765 test_variants (void)
1766 {
1767   guint i;
1768
1769   for (i = 0; i < 100; i++)
1770     test_variant ();
1771
1772   g_variant_type_info_assert_no_infos ();
1773 }
1774
1775 static void
1776 test_strings (void)
1777 {
1778   struct {
1779     guint flags;
1780     guint size;
1781     gconstpointer data;
1782   } test_cases[] = {
1783 #define is_nval           0
1784 #define is_string         1
1785 #define is_objpath        is_string | 2
1786 #define is_sig            is_string | 4
1787     { is_sig,       1, "" },
1788     { is_nval,      0, NULL },
1789     { is_nval,     13, "hello\xffworld!" },
1790     { is_string,   13, "hello world!" },
1791     { is_nval,     13, "hello world\0" },
1792     { is_nval,     13, "hello\0world!" },
1793     { is_nval,     12, "hello world!" },
1794
1795     { is_objpath,   2, "/" },
1796     { is_objpath,   3, "/a" },
1797     { is_string,    3, "//" },
1798     { is_objpath,  11, "/some/path" },
1799     { is_string,   12, "/some/path/" },
1800     { is_nval,     11, "/some\0path" },
1801     { is_string,   11, "/some\\path" },
1802     { is_string,   12, "/some//path" },
1803     { is_string,   12, "/some-/path" },
1804
1805     { is_sig,       2, "i" },
1806     { is_sig,       2, "s" },
1807     { is_sig,       5, "(si)" },
1808     { is_string,    4, "(si" },
1809     { is_string,    2, "*" },
1810     { is_sig,       3, "ai" },
1811     { is_string,    3, "mi" },
1812     { is_string,    2, "r" },
1813     { is_sig,      15, "(yyy{sv}ssiai)" },
1814     { is_string,   16, "(yyy{yv}ssiai))" },
1815     { is_string,   15, "(yyy{vv}ssiai)" },
1816     { is_string,   15, "(yyy{sv)ssiai}" }
1817   };
1818   guint i;
1819
1820   for (i = 0; i < G_N_ELEMENTS (test_cases); i++)
1821     {
1822       guint flags;
1823
1824       flags = g_variant_serialiser_is_string (test_cases[i].data,
1825                                               test_cases[i].size)
1826         ? 1 : 0;
1827
1828       flags |= g_variant_serialiser_is_object_path (test_cases[i].data,
1829                                                     test_cases[i].size)
1830         ? 2 : 0;
1831
1832       flags |= g_variant_serialiser_is_signature (test_cases[i].data,
1833                                                   test_cases[i].size)
1834         ? 4 : 0;
1835
1836       g_assert (flags == test_cases[i].flags);
1837     }
1838 }
1839
1840 typedef struct _TreeInstance TreeInstance;
1841 struct _TreeInstance
1842 {
1843   GVariantTypeInfo *info;
1844
1845   TreeInstance **children;
1846   gsize n_children;
1847
1848   union {
1849     guint64 integer;
1850     gdouble floating;
1851     gchar string[32];
1852   } data;
1853   gsize data_size;
1854 };
1855
1856 static GVariantType *
1857 make_random_definite_type (int depth)
1858 {
1859   GString *description;
1860   GString *type_string;
1861   GVariantType *type;
1862
1863   description = g_string_new (NULL);
1864   type_string = g_string_new (NULL);
1865   type = append_type_string (type_string, description, TRUE, depth);
1866   g_string_free (description, TRUE);
1867   g_string_free (type_string, TRUE);
1868
1869   return type;
1870 }
1871
1872 static void
1873 make_random_string (gchar              *string,
1874                     gsize               size,
1875                     const GVariantType *type)
1876 {
1877   gint i;
1878
1879   /* create strings that are valid signature strings */
1880 #define good_chars "bynqiuxthdsog"
1881
1882   for (i = 0; i < size - 1; i++)
1883     string[i] = good_chars[g_test_rand_int_range (0, strlen (good_chars))];
1884   string[i] = '\0';
1885
1886   /* in case we need an object path, prefix a '/' */
1887   if (*g_variant_type_peek_string (type) == 'o')
1888     string[0] = '/';
1889
1890 #undef good_chars
1891 }
1892
1893 static TreeInstance *
1894 tree_instance_new (const GVariantType *type,
1895                    int                 depth)
1896 {
1897   const GVariantType *child_type = NULL;
1898   GVariantType *mytype = NULL;
1899   TreeInstance *instance;
1900   gboolean is_tuple_type;
1901
1902   if (type == NULL)
1903     type = mytype = make_random_definite_type (depth);
1904
1905   instance = g_slice_new (TreeInstance);
1906   instance->info = g_variant_type_info_get (type);
1907   instance->children = NULL;
1908   instance->n_children = 0;
1909   instance->data_size = 0;
1910
1911   is_tuple_type = FALSE;
1912
1913   switch (*g_variant_type_peek_string (type))
1914     {
1915     case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
1916       instance->n_children = g_test_rand_int_range (0, 2);
1917       child_type = g_variant_type_element (type);
1918       break;
1919
1920     case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
1921       instance->n_children = g_test_rand_int_range (0, MAX_ARRAY_CHILDREN);
1922       child_type = g_variant_type_element (type);
1923       break;
1924
1925     case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
1926     case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
1927       instance->n_children = g_variant_type_n_items (type);
1928       child_type = g_variant_type_first (type);
1929       is_tuple_type = TRUE;
1930       break;
1931
1932     case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
1933       instance->n_children = 1;
1934       child_type = NULL;
1935       break;
1936
1937     case 'b':
1938       instance->data.integer = g_test_rand_int_range (0, 2);
1939       instance->data_size = 1;
1940       break;
1941
1942     case 'y':
1943       instance->data.integer = g_test_rand_int ();
1944       instance->data_size = 1;
1945       break;
1946
1947     case 'n': case 'q':
1948       instance->data.integer = g_test_rand_int ();
1949       instance->data_size = 2;
1950       break;
1951
1952     case 'i': case 'u': case 'h':
1953       instance->data.integer = g_test_rand_int ();
1954       instance->data_size = 4;
1955       break;
1956
1957     case 'x': case 't':
1958       instance->data.integer = g_test_rand_int ();
1959       instance->data.integer <<= 32;
1960       instance->data.integer |= (guint32) g_test_rand_int ();
1961       instance->data_size = 8;
1962       break;
1963
1964     case 'd':
1965       instance->data.floating = g_test_rand_double ();
1966       instance->data_size = 8;
1967       break;
1968
1969     case 's': case 'o': case 'g':
1970       instance->data_size = g_test_rand_int_range (10, 20);
1971       make_random_string (instance->data.string, instance->data_size, type);
1972       break;
1973     }
1974
1975   if (instance->data_size == 0)
1976     /* no data -> it is a container */
1977     {
1978       guint i;
1979
1980       instance->children = g_new (TreeInstance *, instance->n_children);
1981
1982       for (i = 0; i < instance->n_children; i++)
1983         {
1984           instance->children[i] = tree_instance_new (child_type, depth - 1);
1985
1986           if (is_tuple_type)
1987             child_type = g_variant_type_next (child_type);
1988         }
1989
1990       g_assert (!is_tuple_type || child_type == NULL);
1991     }
1992
1993   g_variant_type_free (mytype);
1994
1995   return instance;
1996 }
1997
1998 static void
1999 tree_instance_free (TreeInstance *instance)
2000 {
2001   gint i;
2002
2003   g_variant_type_info_unref (instance->info);
2004   for (i = 0; i < instance->n_children; i++)
2005     tree_instance_free (instance->children[i]);
2006   g_free (instance->children);
2007   g_slice_free (TreeInstance, instance);
2008 }
2009
2010 static gboolean i_am_writing_byteswapped;
2011
2012 static void
2013 tree_filler (GVariantSerialised *serialised,
2014              gpointer            data)
2015 {
2016   TreeInstance *instance = data;
2017
2018   if (serialised->type_info == NULL)
2019     serialised->type_info = instance->info;
2020
2021   if (instance->data_size == 0)
2022     /* is a container */
2023     {
2024       if (serialised->size == 0)
2025         serialised->size =
2026           g_variant_serialiser_needed_size (instance->info, tree_filler,
2027                                             (gpointer *) instance->children,
2028                                             instance->n_children);
2029
2030       if (serialised->data)
2031         g_variant_serialiser_serialise (*serialised, tree_filler,
2032                                         (gpointer *) instance->children,
2033                                         instance->n_children);
2034     }
2035   else
2036     /* it is a leaf */
2037     {
2038       if (serialised->size == 0)
2039         serialised->size = instance->data_size;
2040
2041       if (serialised->data)
2042         {
2043           switch (instance->data_size)
2044             {
2045             case 1:
2046               *serialised->data = instance->data.integer;
2047               break;
2048
2049             case 2:
2050               {
2051                 guint16 value = instance->data.integer;
2052
2053                 if (i_am_writing_byteswapped)
2054                   value = GUINT16_SWAP_LE_BE (value);
2055
2056                 *(guint16 *) serialised->data = value;
2057               }
2058               break;
2059
2060             case 4:
2061               {
2062                 guint32 value = instance->data.integer;
2063
2064                 if (i_am_writing_byteswapped)
2065                   value = GUINT32_SWAP_LE_BE (value);
2066
2067                 *(guint32 *) serialised->data = value;
2068               }
2069               break;
2070
2071             case 8:
2072               {
2073                 guint64 value = instance->data.integer;
2074
2075                 if (i_am_writing_byteswapped)
2076                   value = GUINT64_SWAP_LE_BE (value);
2077
2078                 *(guint64 *) serialised->data = value;
2079               }
2080               break;
2081
2082             default:
2083               memcpy (serialised->data,
2084                       instance->data.string,
2085                       instance->data_size);
2086               break;
2087             }
2088         }
2089     }
2090 }
2091
2092 static gboolean
2093 check_tree (TreeInstance       *instance,
2094             GVariantSerialised  serialised)
2095 {
2096   if (instance->info != serialised.type_info)
2097     return FALSE;
2098
2099   if (instance->data_size == 0)
2100     /* is a container */
2101     {
2102       gint i;
2103
2104       if (g_variant_serialised_n_children (serialised) !=
2105           instance->n_children)
2106         return FALSE;
2107
2108       for (i = 0; i < instance->n_children; i++)
2109         {
2110           GVariantSerialised child;
2111           gpointer data = NULL;
2112           gboolean ok;
2113
2114           child = g_variant_serialised_get_child (serialised, i);
2115           if (child.size && child.data == NULL)
2116             child.data = data = g_malloc0 (child.size);
2117           ok = check_tree (instance->children[i], child);
2118           g_variant_type_info_unref (child.type_info);
2119           g_free (data);
2120
2121           if (!ok)
2122             return FALSE;
2123         }
2124
2125       return TRUE;
2126     }
2127   else
2128     /* it is a leaf */
2129     {
2130       switch (instance->data_size)
2131         {
2132         case 1:
2133           g_assert (serialised.size == 1);
2134           return *(guint8 *) serialised.data ==
2135                   (guint8) instance->data.integer;
2136
2137         case 2:
2138           g_assert (serialised.size == 2);
2139           return *(guint16 *) serialised.data ==
2140                   (guint16) instance->data.integer;
2141
2142         case 4:
2143           g_assert (serialised.size == 4);
2144           return *(guint32 *) serialised.data ==
2145                   (guint32) instance->data.integer;
2146
2147         case 8:
2148           g_assert (serialised.size == 8);
2149           return *(guint64 *) serialised.data ==
2150                   (guint64) instance->data.integer;
2151
2152         default:
2153           if (serialised.size != instance->data_size)
2154             return FALSE;
2155
2156           return memcmp (serialised.data,
2157                          instance->data.string,
2158                          instance->data_size) == 0;
2159         }
2160     }
2161 }
2162
2163 static void
2164 serialise_tree (TreeInstance       *tree,
2165                 GVariantSerialised *serialised)
2166 {
2167   GVariantSerialised empty = {  };
2168
2169   *serialised = empty;
2170   tree_filler (serialised, tree);
2171   serialised->data = g_malloc (serialised->size);
2172   tree_filler (serialised, tree);
2173 }
2174
2175 static void
2176 test_byteswap (void)
2177 {
2178   GVariantSerialised one, two;
2179   TreeInstance *tree;
2180
2181   tree = tree_instance_new (NULL, 3);
2182   serialise_tree (tree, &one);
2183
2184   i_am_writing_byteswapped = TRUE;
2185   serialise_tree (tree, &two);
2186   i_am_writing_byteswapped = FALSE;
2187
2188   g_variant_serialised_byteswap (two);
2189
2190   g_assert_cmpint (one.size, ==, two.size);
2191   g_assert (memcmp (one.data, two.data, one.size) == 0);
2192
2193   tree_instance_free (tree);
2194   g_free (one.data);
2195   g_free (two.data);
2196 }
2197
2198 static void
2199 test_byteswaps (void)
2200 {
2201   int i;
2202
2203   for (i = 0; i < 200; i++)
2204     test_byteswap ();
2205
2206   g_variant_type_info_assert_no_infos ();
2207 }
2208
2209 static void
2210 test_fuzz (gdouble *fuzziness)
2211 {
2212   GVariantSerialised serialised;
2213   TreeInstance *tree;
2214
2215   /* make an instance */
2216   tree = tree_instance_new (NULL, 3);
2217
2218   /* serialise it */
2219   serialise_tree (tree, &serialised);
2220
2221   g_assert (g_variant_serialised_is_normal (serialised));
2222   g_assert (check_tree (tree, serialised));
2223
2224   if (serialised.size)
2225     {
2226       gboolean fuzzed = FALSE;
2227       gboolean a, b;
2228
2229       while (!fuzzed)
2230         {
2231           gint i;
2232
2233           for (i = 0; i < serialised.size; i++)
2234             if (randomly (*fuzziness))
2235               {
2236                 serialised.data[i] += g_test_rand_int_range (1, 256);
2237                 fuzzed = TRUE;
2238               }
2239         }
2240
2241       /* at least one byte in the serialised data has changed.
2242        *
2243        * this means that at least one of the following is true:
2244        *
2245        *    - the serialised data now represents a different value:
2246        *        check_tree() will return FALSE
2247        *
2248        *    - the serialised data is in non-normal form:
2249        *        g_variant_serialiser_is_normal() will return FALSE
2250        *
2251        * we always do both checks to increase exposure of the serialiser
2252        * to corrupt data.
2253        */
2254       a = g_variant_serialised_is_normal (serialised);
2255       b = check_tree (tree, serialised);
2256
2257       g_assert (!a || !b);
2258     }
2259
2260   tree_instance_free (tree);
2261   g_free (serialised.data);
2262 }
2263
2264
2265 static void
2266 test_fuzzes (gpointer data)
2267 {
2268   gdouble fuzziness;
2269   int i;
2270
2271   fuzziness = GPOINTER_TO_INT (data) / 100.;
2272
2273   for (i = 0; i < 200; i++)
2274     test_fuzz (&fuzziness);
2275
2276   g_variant_type_info_assert_no_infos ();
2277 }
2278
2279 static GVariant *
2280 tree_instance_get_gvariant (TreeInstance *tree)
2281 {
2282   const GVariantType *type;
2283   GVariant *result;
2284
2285   type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
2286
2287   switch (g_variant_type_info_get_type_char (tree->info))
2288     {
2289     case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
2290       {
2291         const GVariantType *child_type;
2292         GVariant *child;
2293
2294         if (tree->n_children)
2295           child = tree_instance_get_gvariant (tree->children[0]);
2296         else
2297           child = NULL;
2298
2299         child_type = g_variant_type_element (type);
2300
2301         if (child != NULL && randomly (0.5))
2302           child_type = NULL;
2303
2304         result = g_variant_new_maybe (child_type, child);
2305       }
2306       break;
2307
2308     case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
2309       {
2310         const GVariantType *child_type;
2311         GVariant **children;
2312         gint i;
2313
2314         children = g_new (GVariant *, tree->n_children);
2315         for (i = 0; i < tree->n_children; i++)
2316           children[i] = tree_instance_get_gvariant (tree->children[i]);
2317
2318         child_type = g_variant_type_element (type);
2319
2320         if (i > 0 && randomly (0.5))
2321           child_type = NULL;
2322
2323         result = g_variant_new_array (child_type, children, tree->n_children);
2324         g_free (children);
2325       }
2326       break;
2327
2328     case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
2329       {
2330         GVariant **children;
2331         gint i;
2332
2333         children = g_new (GVariant *, tree->n_children);
2334         for (i = 0; i < tree->n_children; i++)
2335           children[i] = tree_instance_get_gvariant (tree->children[i]);
2336
2337         result = g_variant_new_tuple (children, tree->n_children);
2338         g_free (children);
2339       }
2340       break;
2341
2342     case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
2343       {
2344         GVariant *key, *val;
2345
2346         g_assert (tree->n_children == 2);
2347
2348         key = tree_instance_get_gvariant (tree->children[0]);
2349         val = tree_instance_get_gvariant (tree->children[1]);
2350
2351         result = g_variant_new_dict_entry (key, val);
2352       }
2353       break;
2354
2355     case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
2356       {
2357         GVariant *value;
2358
2359         g_assert (tree->n_children == 1);
2360
2361         value = tree_instance_get_gvariant (tree->children[0]);
2362         result = g_variant_new_variant (value);
2363       }
2364       break;
2365
2366     case 'b':
2367       result = g_variant_new_boolean (tree->data.integer > 0);
2368       break;
2369
2370     case 'y':
2371       result = g_variant_new_byte (tree->data.integer);
2372       break;
2373
2374     case 'n':
2375       result = g_variant_new_int16 (tree->data.integer);
2376       break;
2377
2378     case 'q':
2379       result = g_variant_new_uint16 (tree->data.integer);
2380       break;
2381
2382     case 'i':
2383       result = g_variant_new_int32 (tree->data.integer);
2384       break;
2385
2386     case 'u':
2387       result = g_variant_new_uint32 (tree->data.integer);
2388       break;
2389
2390     case 'x':
2391       result = g_variant_new_int64 (tree->data.integer);
2392       break;
2393
2394     case 't':
2395       result = g_variant_new_uint64 (tree->data.integer);
2396       break;
2397
2398     case 'h':
2399       result = g_variant_new_handle (tree->data.integer);
2400       break;
2401
2402     case 'd':
2403       result = g_variant_new_double (tree->data.floating);
2404       break;
2405
2406     case 's':
2407       result = g_variant_new_string (tree->data.string);
2408       break;
2409
2410     case 'o':
2411       result = g_variant_new_object_path (tree->data.string);
2412       break;
2413
2414     case 'g':
2415       result = g_variant_new_signature (tree->data.string);
2416       break;
2417
2418     default:
2419       g_assert_not_reached ();
2420     }
2421
2422   return result;
2423 }
2424
2425 static gboolean
2426 tree_instance_check_gvariant (TreeInstance *tree,
2427                               GVariant     *value)
2428 {
2429   const GVariantType *type;
2430
2431   type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
2432   g_assert (g_variant_is_of_type (value, type));
2433
2434   switch (g_variant_type_info_get_type_char (tree->info))
2435     {
2436     case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
2437       {
2438         GVariant *child;
2439         gboolean equal;
2440
2441         child = g_variant_get_maybe (value);
2442
2443         if (child != NULL && tree->n_children == 1)
2444           equal = tree_instance_check_gvariant (tree->children[0], child);
2445         else if (child == NULL && tree->n_children == 0)
2446           equal = TRUE;
2447         else
2448           equal = FALSE;
2449
2450         if (child != NULL)
2451           g_variant_unref (child);
2452
2453         return equal;
2454       }
2455       break;
2456
2457     case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
2458     case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
2459     case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
2460       {
2461         gsize i;
2462
2463         if (g_variant_n_children (value) != tree->n_children)
2464           return FALSE;
2465
2466         for (i = 0; i < tree->n_children; i++)
2467           {
2468             GVariant *child;
2469             gboolean equal;
2470
2471             child = g_variant_get_child_value (value, i);
2472             equal = tree_instance_check_gvariant (tree->children[i], child);
2473             g_variant_unref (child);
2474
2475             if (!equal)
2476               return FALSE;
2477           }
2478
2479         return TRUE;
2480       }
2481       break;
2482
2483     case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
2484       {
2485         const gchar *str1, *str2;
2486         GVariant *child;
2487         gboolean equal;
2488
2489         child = g_variant_get_variant (value);
2490         str1 = g_variant_get_type_string (child);
2491         str2 = g_variant_type_info_get_type_string (tree->children[0]->info);
2492         /* GVariant only keeps one copy of type strings around */
2493         equal = str1 == str2 &&
2494                 tree_instance_check_gvariant (tree->children[0], child);
2495
2496         g_variant_unref (child);
2497
2498         return equal;
2499       }
2500       break;
2501
2502     case 'b':
2503       return g_variant_get_boolean (value) == tree->data.integer;
2504
2505     case 'y':
2506       return g_variant_get_byte (value) == (guchar) tree->data.integer;
2507
2508     case 'n':
2509       return g_variant_get_int16 (value) == (gint16) tree->data.integer;
2510
2511     case 'q':
2512       return g_variant_get_uint16 (value) == (guint16) tree->data.integer;
2513
2514     case 'i':
2515       return g_variant_get_int32 (value) == (gint32) tree->data.integer;
2516
2517     case 'u':
2518       return g_variant_get_uint32 (value) == (guint32) tree->data.integer;
2519
2520     case 'x':
2521       return g_variant_get_int64 (value) == (gint64) tree->data.integer;
2522
2523     case 't':
2524       return g_variant_get_uint64 (value) == (guint64) tree->data.integer;
2525
2526     case 'h':
2527       return g_variant_get_handle (value) == (gint32) tree->data.integer;
2528
2529     case 'd':
2530       {
2531         gdouble floating = g_variant_get_double (value);
2532
2533         return memcmp (&floating, &tree->data.floating, sizeof floating) == 0;
2534       }
2535
2536     case 's':
2537     case 'o':
2538     case 'g':
2539       return strcmp (g_variant_get_string (value, NULL),
2540                      tree->data.string) == 0;
2541
2542     default:
2543       g_assert_not_reached ();
2544     }
2545 }
2546
2547 static void
2548 tree_instance_build_gvariant (TreeInstance    *tree,
2549                               GVariantBuilder *builder,
2550                               gboolean         guess_ok)
2551 {
2552   const GVariantType *type;
2553
2554   type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
2555
2556   if (g_variant_type_is_container (type))
2557     {
2558       gsize i;
2559
2560       /* force GVariantBuilder to guess the type half the time */
2561       if (guess_ok && randomly (0.5))
2562         {
2563           if (g_variant_type_is_array (type) && tree->n_children)
2564             type = G_VARIANT_TYPE_ARRAY;
2565
2566           if (g_variant_type_is_maybe (type) && tree->n_children)
2567             type = G_VARIANT_TYPE_MAYBE;
2568
2569           if (g_variant_type_is_tuple (type))
2570             type = G_VARIANT_TYPE_TUPLE;
2571
2572           if (g_variant_type_is_dict_entry (type))
2573             type = G_VARIANT_TYPE_DICT_ENTRY;
2574         }
2575       else
2576         guess_ok = FALSE;
2577
2578       g_variant_builder_open (builder, type);
2579
2580       for (i = 0; i < tree->n_children; i++)
2581         tree_instance_build_gvariant (tree->children[i], builder, guess_ok);
2582
2583       g_variant_builder_close (builder);
2584     }
2585   else
2586     g_variant_builder_add_value (builder, tree_instance_get_gvariant (tree));
2587 }
2588
2589
2590 static gboolean
2591 tree_instance_check_iter (TreeInstance *tree,
2592                           GVariantIter *iter)
2593 {
2594   GVariant *value;
2595
2596   value = g_variant_iter_next_value (iter);
2597
2598   if (g_variant_is_container (value))
2599     {
2600       gsize i;
2601
2602       iter = g_variant_iter_new (value);
2603       g_variant_unref (value);
2604
2605       if (g_variant_iter_n_children (iter) != tree->n_children)
2606         {
2607           g_variant_iter_free (iter);
2608           return FALSE;
2609         }
2610
2611       for (i = 0; i < tree->n_children; i++)
2612         if (!tree_instance_check_iter (tree->children[i], iter))
2613           {
2614             g_variant_iter_free (iter);
2615             return FALSE;
2616           }
2617
2618       g_assert (g_variant_iter_next_value (iter) == NULL);
2619       g_variant_iter_free (iter);
2620
2621       return TRUE;
2622     }
2623
2624   else
2625     {
2626       gboolean equal;
2627
2628       equal = tree_instance_check_gvariant (tree, value);
2629       g_variant_unref (value);
2630
2631       return equal;
2632     }
2633 }
2634
2635 static void
2636 test_container (void)
2637 {
2638   TreeInstance *tree;
2639   GVariant *value;
2640   gchar *s1, *s2;
2641
2642   tree = tree_instance_new (NULL, 3);
2643   value = g_variant_ref_sink (tree_instance_get_gvariant (tree));
2644
2645   s1 = g_variant_print (value, TRUE);
2646   g_assert (tree_instance_check_gvariant (tree, value));
2647
2648   g_variant_get_data (value);
2649
2650   s2 = g_variant_print (value, TRUE);
2651   g_assert (tree_instance_check_gvariant (tree, value));
2652
2653   g_assert_cmpstr (s1, ==, s2);
2654
2655   if (g_variant_is_container (value))
2656     {
2657       GVariantBuilder builder;
2658       GVariantIter iter;
2659       GVariant *built;
2660       GVariant *val;
2661       gchar *s3;
2662
2663       g_variant_builder_init (&builder, G_VARIANT_TYPE_VARIANT);
2664       tree_instance_build_gvariant (tree, &builder, TRUE);
2665       built = g_variant_builder_end (&builder);
2666       g_variant_ref_sink (built);
2667       g_variant_get_data (built);
2668       val = g_variant_get_variant (built);
2669
2670       s3 = g_variant_print (val, TRUE);
2671       g_assert_cmpstr (s1, ==, s3);
2672
2673       g_variant_iter_init (&iter, built);
2674       g_assert (tree_instance_check_iter (tree, &iter));
2675       g_assert (g_variant_iter_next_value (&iter) == NULL);
2676
2677       g_variant_unref (built);
2678       g_variant_unref (val);
2679       g_free (s3);
2680     }
2681
2682   tree_instance_free (tree);
2683   g_variant_unref (value);
2684   g_free (s2);
2685   g_free (s1);
2686 }
2687
2688 static void
2689 test_utf8 (void)
2690 {
2691   const gchar invalid[] = "hello\xffworld";
2692   GVariant *value;
2693
2694   /* ensure that the test data is not valid utf8... */
2695   g_assert (!g_utf8_validate (invalid, -1, NULL));
2696
2697   /* load the data untrusted */
2698   value = g_variant_new_from_data (G_VARIANT_TYPE_STRING,
2699                                    invalid, sizeof invalid,
2700                                    FALSE, NULL, NULL);
2701
2702   /* ensure that the problem is caught and we get valid UTF-8 */
2703   g_assert (g_utf8_validate (g_variant_get_string (value, NULL), -1, NULL));
2704   g_variant_unref (value);
2705
2706
2707   /* now load it trusted */
2708   value = g_variant_new_from_data (G_VARIANT_TYPE_STRING,
2709                                    invalid, sizeof invalid,
2710                                    TRUE, NULL, NULL);
2711
2712   /* ensure we get the invalid data (ie: make sure that time wasn't
2713    * wasted on validating data that was marked as trusted)
2714    */
2715   g_assert (g_variant_get_string (value, NULL) == invalid);
2716   g_variant_unref (value);
2717 }
2718
2719 static void
2720 test_containers (void)
2721 {
2722   gint i;
2723
2724   for (i = 0; i < 100; i++)
2725     {
2726       test_container ();
2727     }
2728
2729   g_variant_type_info_assert_no_infos ();
2730 }
2731
2732 static void
2733 test_format_strings (void)
2734 {
2735   GVariantType *type;
2736   const gchar *end;
2737
2738   g_assert (g_variant_format_string_scan ("i", NULL, &end) && *end == '\0');
2739   g_assert (g_variant_format_string_scan ("@i", NULL, &end) && *end == '\0');
2740   g_assert (g_variant_format_string_scan ("@ii", NULL, &end) && *end == 'i');
2741   g_assert (g_variant_format_string_scan ("^a&s", NULL, &end) && *end == '\0');
2742   g_assert (g_variant_format_string_scan ("(^as)", NULL, &end) &&
2743             *end == '\0');
2744   g_assert (!g_variant_format_string_scan ("(^s)", NULL, &end));
2745   g_assert (!g_variant_format_string_scan ("(^a)", NULL, &end));
2746   g_assert (!g_variant_format_string_scan ("(z)", NULL, &end));
2747   g_assert (!g_variant_format_string_scan ("az", NULL, &end));
2748   g_assert (!g_variant_format_string_scan ("{**}", NULL, &end));
2749   g_assert (!g_variant_format_string_scan ("{@**}", NULL, &end));
2750   g_assert (g_variant_format_string_scan ("{@y*}", NULL, &end) &&
2751             *end == '\0');
2752   g_assert (g_variant_format_string_scan ("{yv}", NULL, &end) &&
2753             *end == '\0');
2754   g_assert (!g_variant_format_string_scan ("{&?v}", NULL, &end));
2755   g_assert (g_variant_format_string_scan ("{@?v}", NULL, &end) &&
2756             *end == '\0');
2757   g_assert (!g_variant_format_string_scan ("{&@sv}", NULL, &end));
2758   g_assert (!g_variant_format_string_scan ("{@&sv}", NULL, &end));
2759   g_assert (g_variant_format_string_scan ("{&sv}", NULL, &end) &&
2760             *end == '\0');
2761   g_assert (!g_variant_format_string_scan ("{vv}", NULL, &end));
2762   g_assert (!g_variant_format_string_scan ("{y}", NULL, &end));
2763   g_assert (!g_variant_format_string_scan ("{yyy}", NULL, &end));
2764   g_assert (!g_variant_format_string_scan ("{ya}", NULL, &end));
2765   g_assert (g_variant_format_string_scan ("&s", NULL, &end) && *end == '\0');
2766   g_assert (!g_variant_format_string_scan ("&as", NULL, &end));
2767   g_assert (!g_variant_format_string_scan ("@z", NULL, &end));
2768   g_assert (!g_variant_format_string_scan ("az", NULL, &end));
2769   g_assert (!g_variant_format_string_scan ("a&s", NULL, &end));
2770
2771   type = g_variant_format_string_scan_type ("mm(@xy^a&s*?@?)", NULL, &end);
2772   g_assert (type && *end == '\0');
2773   g_assert (g_variant_type_equal (type, G_VARIANT_TYPE ("mm(xyas*?\?)")));
2774   g_variant_type_free (type);
2775
2776   type = g_variant_format_string_scan_type ("mm(@xy^a&*?@?)", NULL, NULL);
2777   g_assert (type == NULL);
2778 }
2779
2780 static void
2781 exit_on_abort (int signal)
2782 {
2783   exit (signal);
2784 }
2785
2786 static gboolean
2787 do_failed_test (const gchar *pattern)
2788 {
2789   if (g_test_trap_fork (1000000, G_TEST_TRAP_SILENCE_STDERR))
2790     {
2791       signal (SIGABRT, exit_on_abort);
2792       return TRUE;
2793     }
2794
2795   g_test_trap_assert_failed ();
2796   g_test_trap_assert_stderr (pattern);
2797
2798   return FALSE;
2799 }
2800
2801 static void
2802 test_invalid_varargs (void)
2803 {
2804   if (do_failed_test ("*GVariant format string*"))
2805     {
2806       g_variant_new ("z");
2807       abort ();
2808     }
2809
2810   if (do_failed_test ("*valid GVariant format string as a prefix*"))
2811     {
2812       const gchar *end;
2813
2814       g_variant_new_va ("z", &end, NULL);
2815       abort ();
2816     }
2817
2818   if (do_failed_test ("*type of `q' but * has a type of `y'*"))
2819     {
2820       g_variant_get (g_variant_new ("y", 'a'), "q");
2821       abort ();
2822     }
2823 }
2824
2825 static void
2826 check_and_free (GVariant    *value,
2827                 const gchar *str)
2828 {
2829   gchar *valstr = g_variant_print (value, FALSE);
2830   g_assert_cmpstr (str, ==, valstr);
2831   g_variant_unref (value);
2832   g_free (valstr);
2833 }
2834
2835 static void
2836 test_varargs (void)
2837 {
2838   {
2839     GVariantBuilder array;
2840
2841     g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
2842     g_variant_builder_add (&array, "{sv}", "size",
2843                            g_variant_new ("(ii)", 800, 600));
2844     g_variant_builder_add (&array, "{sv}", "title",
2845                            g_variant_new_string ("Test case"));
2846     g_variant_builder_add_value (&array,
2847       g_variant_new_dict_entry (g_variant_new_string ("temperature"),
2848                                 g_variant_new_variant (
2849                                   g_variant_new_double (37.5))));
2850     check_and_free (g_variant_new ("(ma{sv}m(a{sv})ma{sv}ii)",
2851                                    NULL, FALSE, NULL, &array, 7777, 8888),
2852                     "(nothing, nothing, {'size': <(800, 600)>, "
2853                                         "'title': <'Test case'>, "
2854                                         "'temperature': <37.5>}, "
2855                      "7777, 8888)");
2856
2857     check_and_free (g_variant_new ("(imimimmimmimmi)",
2858                                    123,
2859                                    FALSE, 321,
2860                                    TRUE, 123,
2861                                    FALSE, TRUE, 321,
2862                                    TRUE, FALSE, 321,
2863                                    TRUE, TRUE, 123),
2864                     "(123, nothing, 123, nothing, just nothing, 123)");
2865
2866     check_and_free (g_variant_new ("(ybnixd)",
2867                                    'a', 1, 22, 33, (guint64) 44, 5.5),
2868                     "(0x61, true, 22, 33, 44, 5.5)");
2869
2870     check_and_free (g_variant_new ("(@y?*rv)",
2871                                    g_variant_new ("y", 'a'),
2872                                    g_variant_new ("y", 'b'),
2873                                    g_variant_new ("y", 'c'),
2874                                    g_variant_new ("(y)", 'd'),
2875                                    g_variant_new ("y", 'e')),
2876                     "(0x61, 0x62, 0x63, (0x64,), <byte 0x65>)");
2877   }
2878
2879   {
2880     GVariantBuilder array;
2881     GVariantIter iter;
2882     GVariant *value;
2883     gchar *number;
2884     gboolean just;
2885     gint i, val;
2886
2887     g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
2888     for (i = 0; i < 100; i++)
2889       {
2890         number = g_strdup_printf ("%d", i);
2891         g_variant_builder_add (&array, "s", number);
2892         g_free (number);
2893       }
2894
2895     value = g_variant_builder_end (&array);
2896     g_variant_iter_init (&iter, value);
2897
2898     i = 0;
2899     while (g_variant_iter_loop (&iter, "s", &number))
2900       {
2901         gchar *check = g_strdup_printf ("%d", i++);
2902         g_assert_cmpstr (number, ==, check);
2903         g_free (check);
2904       }
2905     g_assert (number == NULL);
2906     g_assert (i == 100);
2907
2908     g_variant_unref (value);
2909
2910     g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
2911     for (i = 0; i < 100; i++)
2912       g_variant_builder_add (&array, "mi", i % 2 == 0, i);
2913     value = g_variant_builder_end (&array);
2914
2915     i = 0;
2916     g_variant_iter_init (&iter, value);
2917     while (g_variant_iter_loop (&iter, "mi", NULL, &val))
2918       g_assert (val == i++ || val == 0);
2919     g_assert (i == 100);
2920
2921     i = 0;
2922     g_variant_iter_init (&iter, value);
2923     while (g_variant_iter_loop (&iter, "mi", &just, &val))
2924       {
2925         gint this = i++;
2926
2927         if (this % 2 == 0)
2928           {
2929             g_assert (just);
2930             g_assert (val == this);
2931           }
2932         else
2933           {
2934             g_assert (!just);
2935             g_assert (val == 0);
2936           }
2937       }
2938     g_assert (i == 100);
2939
2940     g_variant_unref (value);
2941   }
2942
2943   {
2944     const gchar *strvector[] = {"/hello", "/world", NULL};
2945     const gchar *test_strs[] = {"/foo", "/bar", "/baz" };
2946     GVariantBuilder builder;
2947     GVariantIter *array;
2948     GVariantIter tuple;
2949     const gchar **strv;
2950     gchar **my_strv;
2951     GVariant *value;
2952     gchar *str;
2953     gint i;
2954
2955     g_variant_builder_init (&builder, G_VARIANT_TYPE ("ao"));
2956     g_variant_builder_add (&builder, "o", "/foo");
2957     g_variant_builder_add (&builder, "o", "/bar");
2958     g_variant_builder_add (&builder, "o", "/baz");
2959     value = g_variant_new("(ao^ao^a&o)", &builder, strvector, strvector);
2960     g_variant_iter_init (&tuple, value);
2961     g_variant_iter_next (&tuple, "ao", &array);
2962
2963     i = 0;
2964     while (g_variant_iter_loop (array, "o", &str))
2965       g_assert_cmpstr (str, ==, test_strs[i++]);
2966     g_assert (i == 3);
2967
2968     g_variant_iter_free (array);
2969
2970     /* start over */
2971     g_variant_iter_init (&tuple, value);
2972     g_variant_iter_next (&tuple, "ao", &array);
2973
2974     i = 0;
2975     while (g_variant_iter_loop (array, "&o", &str))
2976       g_assert_cmpstr (str, ==, test_strs[i++]);
2977     g_assert (i == 3);
2978
2979     g_variant_iter_free (array);
2980
2981     g_variant_iter_next (&tuple, "^a&o", &strv);
2982     g_variant_iter_next (&tuple, "^ao", &my_strv);
2983
2984     g_assert_cmpstr (strv[0], ==, "/hello");
2985     g_assert_cmpstr (strv[1], ==, "/world");
2986     g_assert (strv[2] == NULL);
2987     g_assert_cmpstr (my_strv[0], ==, "/hello");
2988     g_assert_cmpstr (my_strv[1], ==, "/world");
2989     g_assert (my_strv[2] == NULL);
2990
2991     g_variant_unref (value);
2992     g_strfreev (my_strv);
2993     g_free (strv);
2994   }
2995
2996   {
2997     const gchar *strvector[] = { "i", "ii", "iii", "iv", "v", "vi", NULL };
2998     GVariantBuilder builder;
2999     GVariantIter iter;
3000     GVariantIter *i2;
3001     GVariantIter *i3;
3002     GVariant *value;
3003     GVariant *sub;
3004     gchar **strv;
3005     gint i;
3006
3007     g_variant_builder_init (&builder, G_VARIANT_TYPE ("aag"));
3008     g_variant_builder_open (&builder, G_VARIANT_TYPE ("ag"));
3009     for (i = 0; i < 6; i++)
3010       if (i & 1)
3011         g_variant_builder_add (&builder, "g", strvector[i]);
3012       else
3013         g_variant_builder_add (&builder, "&g", strvector[i]);
3014     g_variant_builder_close (&builder);
3015     g_variant_builder_add (&builder, "^ag", strvector);
3016     g_variant_builder_add (&builder, "^ag", strvector);
3017     value = g_variant_new ("aag", &builder);
3018
3019     g_variant_iter_init (&iter, value);
3020     while (g_variant_iter_loop (&iter, "^ag", &strv))
3021       for (i = 0; i < 6; i++)
3022         g_assert_cmpstr (strv[i], ==, strvector[i]);
3023
3024     g_variant_iter_init (&iter, value);
3025     while (g_variant_iter_loop (&iter, "^a&g", &strv))
3026       for (i = 0; i < 6; i++)
3027         g_assert_cmpstr (strv[i], ==, strvector[i]);
3028
3029     g_variant_iter_init (&iter, value);
3030     while (g_variant_iter_loop (&iter, "ag", &i2))
3031       {
3032         gchar *str;
3033
3034         i = 0;
3035         while (g_variant_iter_loop (i2, "g", &str))
3036           g_assert_cmpstr (str, ==, strvector[i++]);
3037         g_assert (i == 6);
3038       }
3039
3040     g_variant_iter_init (&iter, value);
3041     i3 = g_variant_iter_copy (&iter);
3042     while (g_variant_iter_loop (&iter, "@ag", &sub))
3043       {
3044         gchar *str = g_variant_print (sub, TRUE);
3045         g_assert_cmpstr (str, ==,
3046                          "[signature 'i', 'ii', 'iii', 'iv', 'v', 'vi']");
3047         g_free (str);
3048       }
3049
3050   if (do_failed_test ("*NULL has already been returned*"))
3051     {
3052       g_variant_iter_next_value (&iter);
3053       abort ();
3054     }
3055
3056
3057     while (g_variant_iter_loop (i3, "*", &sub))
3058       {
3059         gchar *str = g_variant_print (sub, TRUE);
3060         g_assert_cmpstr (str, ==,
3061                          "[signature 'i', 'ii', 'iii', 'iv', 'v', 'vi']");
3062         g_free (str);
3063       }
3064
3065     g_variant_iter_free (i3);
3066
3067     for (i = 0; i < g_variant_n_children (value); i++)
3068       {
3069         gint j;
3070
3071         g_variant_get_child (value, i, "*", &sub);
3072
3073         for (j = 0; j < g_variant_n_children (sub); j++)
3074           {
3075             const gchar *str = NULL;
3076             GVariant *cval;
3077
3078             g_variant_get_child (sub, j, "&g", &str);
3079             g_assert_cmpstr (str, ==, strvector[j]);
3080
3081             cval = g_variant_get_child_value (sub, j);
3082             g_variant_get (cval, "&g", &str);
3083             g_assert_cmpstr (str, ==, strvector[j]);
3084             g_variant_unref (cval);
3085           }
3086
3087         g_variant_unref (sub);
3088       }
3089
3090     g_variant_unref (value);
3091   }
3092
3093   {
3094     gboolean justs[10];
3095     GVariant *value;
3096
3097     GVariant *vval;
3098     guchar byteval;
3099     gboolean bval;
3100     gint16 i16val;
3101     guint16 u16val;
3102     gint32 i32val;
3103     guint32 u32val;
3104     gint64 i64val;
3105     guint64 u64val;
3106     gdouble dval;
3107     gint32 hval;
3108
3109     /* test all 'nothing' */
3110     value = g_variant_new ("(mymbmnmqmimumxmtmhmdmv)",
3111                            FALSE, 'a',
3112                            FALSE, TRUE,
3113                            FALSE, (gint16) 123,
3114                            FALSE, (guint16) 123,
3115                            FALSE, (gint32) 123,
3116                            FALSE, (guint32) 123,
3117                            FALSE, (gint64) 123,
3118                            FALSE, (guint64) 123,
3119                            FALSE, (gint32) -1,
3120                            FALSE, (gdouble) 37.5,
3121                            NULL);
3122
3123     /* both NULL */
3124     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3125                    NULL, NULL,
3126                    NULL, NULL,
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);
3136
3137     /* NULL values */
3138     memset (justs, 1, sizeof justs);
3139     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3140                    &justs[0], NULL,
3141                    &justs[1], NULL,
3142                    &justs[2], NULL,
3143                    &justs[3], NULL,
3144                    &justs[4], NULL,
3145                    &justs[5], NULL,
3146                    &justs[6], NULL,
3147                    &justs[7], NULL,
3148                    &justs[8], NULL,
3149                    &justs[9], NULL,
3150                    NULL);
3151     g_assert (!(justs[0] || justs[1] || justs[2] || justs[3] || justs[4] ||
3152                 justs[5] || justs[6] || justs[7] || justs[8] || justs[9]));
3153
3154     /* both non-NULL */
3155     memset (justs, 1, sizeof justs);
3156     byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3157     vval = (void *) 1;
3158     bval = TRUE;
3159     dval = 88.88;
3160     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3161                    &justs[0], &byteval,
3162                    &justs[1], &bval,
3163                    &justs[2], &i16val,
3164                    &justs[3], &u16val,
3165                    &justs[4], &i32val,
3166                    &justs[5], &u32val,
3167                    &justs[6], &i64val,
3168                    &justs[7], &u64val,
3169                    &justs[8], &hval,
3170                    &justs[9], &dval,
3171                    &vval);
3172     g_assert (!(justs[0] || justs[1] || justs[2] || justs[3] || justs[4] ||
3173                 justs[5] || justs[6] || justs[7] || justs[8] || justs[9]));
3174     g_assert (byteval == '\0' && bval == FALSE);
3175     g_assert (i16val == 0 && u16val == 0 && i32val == 0 &&
3176               u32val == 0 && i64val == 0 && u64val == 0 &&
3177               hval == 0 && dval == 0.0);
3178     g_assert (vval == NULL);
3179
3180     /* NULL justs */
3181     byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3182     vval = (void *) 1;
3183     bval = TRUE;
3184     dval = 88.88;
3185     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3186                    NULL, &byteval,
3187                    NULL, &bval,
3188                    NULL, &i16val,
3189                    NULL, &u16val,
3190                    NULL, &i32val,
3191                    NULL, &u32val,
3192                    NULL, &i64val,
3193                    NULL, &u64val,
3194                    NULL, &hval,
3195                    NULL, &dval,
3196                    &vval);
3197     g_assert (byteval == '\0' && bval == FALSE);
3198     g_assert (i16val == 0 && u16val == 0 && i32val == 0 &&
3199               u32val == 0 && i64val == 0 && u64val == 0 &&
3200               hval == 0 && dval == 0.0);
3201     g_assert (vval == NULL);
3202
3203     g_variant_unref (value);
3204
3205
3206     /* test all 'just' */
3207     value = g_variant_new ("(mymbmnmqmimumxmtmhmdmv)",
3208                            TRUE, 'a',
3209                            TRUE, TRUE,
3210                            TRUE, (gint16) 123,
3211                            TRUE, (guint16) 123,
3212                            TRUE, (gint32) 123,
3213                            TRUE, (guint32) 123,
3214                            TRUE, (gint64) 123,
3215                            TRUE, (guint64) 123,
3216                            TRUE, (gint32) -1,
3217                            TRUE, (gdouble) 37.5,
3218                            g_variant_new ("()"));
3219
3220     /* both NULL */
3221     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3222                    NULL, NULL,
3223                    NULL, NULL,
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);
3233
3234     /* NULL values */
3235     memset (justs, 0, sizeof justs);
3236     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3237                    &justs[0], NULL,
3238                    &justs[1], NULL,
3239                    &justs[2], NULL,
3240                    &justs[3], NULL,
3241                    &justs[4], NULL,
3242                    &justs[5], NULL,
3243                    &justs[6], NULL,
3244                    &justs[7], NULL,
3245                    &justs[8], NULL,
3246                    &justs[9], NULL,
3247                    NULL);
3248     g_assert (justs[0] && justs[1] && justs[2] && justs[3] && justs[4] &&
3249               justs[5] && justs[6] && justs[7] && justs[8] && justs[9]);
3250
3251     /* both non-NULL */
3252     memset (justs, 0, sizeof justs);
3253     byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3254     vval = (void *) 1;
3255     bval = FALSE;
3256     dval = 88.88;
3257     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3258                    &justs[0], &byteval,
3259                    &justs[1], &bval,
3260                    &justs[2], &i16val,
3261                    &justs[3], &u16val,
3262                    &justs[4], &i32val,
3263                    &justs[5], &u32val,
3264                    &justs[6], &i64val,
3265                    &justs[7], &u64val,
3266                    &justs[8], &hval,
3267                    &justs[9], &dval,
3268                    &vval);
3269     g_assert (justs[0] && justs[1] && justs[2] && justs[3] && justs[4] &&
3270               justs[5] && justs[6] && justs[7] && justs[8] && justs[9]);
3271     g_assert (byteval == 'a' && bval == TRUE);
3272     g_assert (i16val == 123 && u16val == 123 && i32val == 123 &&
3273               u32val == 123 && i64val == 123 && u64val == 123 &&
3274               hval == -1 && dval == 37.5);
3275     g_assert (g_variant_is_of_type (vval, G_VARIANT_TYPE_UNIT));
3276     g_variant_unref (vval);
3277
3278     /* NULL justs */
3279     byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3280     vval = (void *) 1;
3281     bval = TRUE;
3282     dval = 88.88;
3283     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3284                    NULL, &byteval,
3285                    NULL, &bval,
3286                    NULL, &i16val,
3287                    NULL, &u16val,
3288                    NULL, &i32val,
3289                    NULL, &u32val,
3290                    NULL, &i64val,
3291                    NULL, &u64val,
3292                    NULL, &hval,
3293                    NULL, &dval,
3294                    &vval);
3295     g_assert (byteval == 'a' && bval == TRUE);
3296     g_assert (i16val == 123 && u16val == 123 && i32val == 123 &&
3297               u32val == 123 && i64val == 123 && u64val == 123 &&
3298               hval == -1 && dval == 37.5);
3299     g_assert (g_variant_is_of_type (vval, G_VARIANT_TYPE_UNIT));
3300     g_variant_unref (vval);
3301
3302     g_variant_unref (value);
3303   }
3304
3305   g_variant_type_info_assert_no_infos ();
3306 }
3307
3308 static void
3309 hash_get (GVariant    *value,
3310           const gchar *format,
3311           ...)
3312 {
3313   const gchar *endptr = NULL;
3314   gboolean hash;
3315   va_list ap;
3316
3317   hash = g_str_has_suffix (format, "#");
3318
3319   va_start (ap, format);
3320   g_variant_get_va (value, format, hash ? &endptr : NULL, &ap);
3321   va_end (ap);
3322
3323   if (hash)
3324     g_assert (*endptr == '#');
3325 }
3326
3327 static GVariant *
3328 hash_new (const gchar *format,
3329           ...)
3330 {
3331   const gchar *endptr = NULL;
3332   GVariant *value;
3333   gboolean hash;
3334   va_list ap;
3335
3336   hash = g_str_has_suffix (format, "#");
3337
3338   va_start (ap, format);
3339   value = g_variant_new_va (format, hash ? &endptr : NULL, &ap);
3340   va_end (ap);
3341
3342   if (hash)
3343     g_assert (*endptr == '#');
3344
3345   return value;
3346 }
3347
3348 static void
3349 test_valist (void)
3350 {
3351   GVariant *value;
3352   gint32 x;
3353
3354   x = 0;
3355   value = hash_new ("i", 234);
3356   hash_get (value, "i", &x);
3357   g_assert (x == 234);
3358   g_variant_unref (value);
3359
3360   x = 0;
3361   value = hash_new ("i#", 234);
3362   hash_get (value, "i#", &x);
3363   g_assert (x == 234);
3364   g_variant_unref (value);
3365
3366   g_variant_type_info_assert_no_infos ();
3367 }
3368
3369 static void
3370 test_builder_memory (void)
3371 {
3372   GVariantBuilder *hb;
3373   GVariantBuilder sb;
3374
3375   hb = g_variant_builder_new  (G_VARIANT_TYPE_ARRAY);
3376   g_variant_builder_open (hb, G_VARIANT_TYPE_ARRAY);
3377   g_variant_builder_open (hb, G_VARIANT_TYPE_ARRAY);
3378   g_variant_builder_open (hb, G_VARIANT_TYPE_ARRAY);
3379   g_variant_builder_add (hb, "s", "some value");
3380   g_variant_builder_ref (hb);
3381   g_variant_builder_unref (hb);
3382   g_variant_builder_unref (hb);
3383
3384   hb = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
3385   g_variant_builder_unref (hb);
3386
3387   hb = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
3388   g_variant_builder_clear (hb);
3389   g_variant_builder_unref (hb);
3390
3391   g_variant_builder_init (&sb, G_VARIANT_TYPE_ARRAY);
3392   g_variant_builder_open (&sb, G_VARIANT_TYPE_ARRAY);
3393   g_variant_builder_open (&sb, G_VARIANT_TYPE_ARRAY);
3394   g_variant_builder_add (&sb, "s", "some value");
3395   g_variant_builder_clear (&sb);
3396
3397   g_variant_type_info_assert_no_infos ();
3398 }
3399
3400 static void
3401 test_hashing (void)
3402 {
3403   GVariant *items[4096];
3404   GHashTable *table;
3405   gint i;
3406
3407   table = g_hash_table_new_full (g_variant_hash, g_variant_equal,
3408                                  (GDestroyNotify ) g_variant_unref,
3409                                  NULL);
3410
3411   for (i = 0; i < G_N_ELEMENTS (items); i++)
3412     {
3413       TreeInstance *tree;
3414       gint j;
3415
3416  again:
3417       tree = tree_instance_new (NULL, 0);
3418       items[i] = tree_instance_get_gvariant (tree);
3419       tree_instance_free (tree);
3420
3421       for (j = 0; j < i; j++)
3422         if (g_variant_equal (items[i], items[j]))
3423           {
3424             g_variant_unref (items[i]);
3425             goto again;
3426           }
3427
3428       g_hash_table_insert (table,
3429                            g_variant_ref_sink (items[i]),
3430                            GINT_TO_POINTER (i));
3431     }
3432
3433   for (i = 0; i < G_N_ELEMENTS (items); i++)
3434     {
3435       gpointer result;
3436
3437       result = g_hash_table_lookup (table, items[i]);
3438       g_assert_cmpint (GPOINTER_TO_INT (result), ==, i);
3439     }
3440
3441   g_hash_table_unref (table);
3442
3443   g_variant_type_info_assert_no_infos ();
3444 }
3445
3446 static void
3447 test_gv_byteswap ()
3448 {
3449 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
3450 # define native16(x)  x, 0
3451 # define swapped16(x) 0, x
3452 #else
3453 # define native16(x)  0, x
3454 # define swapped16(x) x, 0
3455 #endif
3456   /* all kinds of of crazy randomised testing already performed on the
3457    * byteswapper in the /gvariant/serialiser/byteswap test and all kinds
3458    * of crazy randomised testing performed against the serialiser
3459    * normalisation functions in the /gvariant/serialiser/fuzz/ tests.
3460    *
3461    * just test a few simple cases here to make sure they each work
3462    */
3463   guchar valid_data[] = { 'a', '\0', swapped16(66), 2,
3464                           0,
3465                           'b', '\0', swapped16(77), 2,
3466                           5, 11 };
3467   guchar corrupt_data[] = { 'a', '\0', swapped16(66), 2,
3468                             0,
3469                             'b', '\0', swapped16(77), 2,
3470                             6, 11 };
3471   GVariant *value, *swapped;
3472   gchar *string, *string2;
3473
3474
3475   /* trusted */
3476   value = g_variant_new_from_data (G_VARIANT_TYPE ("a(sn)"),
3477                                    valid_data, sizeof valid_data, TRUE,
3478                                    NULL, NULL);
3479   swapped = g_variant_byteswap (value);
3480   g_variant_unref (value);
3481   g_assert (g_variant_get_size (swapped) == 13);
3482   string = g_variant_print (swapped, FALSE);
3483   g_variant_unref (swapped);
3484   g_assert_cmpstr (string, ==, "[('a', 66), ('b', 77)]");
3485   g_free (string);
3486
3487   /* untrusted but valid */
3488   value = g_variant_new_from_data (G_VARIANT_TYPE ("a(sn)"),
3489                                    valid_data, sizeof valid_data, FALSE,
3490                                    NULL, NULL);
3491   swapped = g_variant_byteswap (value);
3492   g_variant_unref (value);
3493   g_assert (g_variant_get_size (swapped) == 13);
3494   string = g_variant_print (swapped, FALSE);
3495   g_variant_unref (swapped);
3496   g_assert_cmpstr (string, ==, "[('a', 66), ('b', 77)]");
3497   g_free (string);
3498
3499   /* untrusted, invalid */
3500   value = g_variant_new_from_data (G_VARIANT_TYPE ("a(sn)"),
3501                                    corrupt_data, sizeof corrupt_data, FALSE,
3502                                    NULL, NULL);
3503   string = g_variant_print (value, FALSE);
3504   swapped = g_variant_byteswap (value);
3505   g_variant_unref (value);
3506   g_assert (g_variant_get_size (swapped) == 13);
3507   value = g_variant_byteswap (swapped);
3508   g_variant_unref (swapped);
3509   string2 = g_variant_print (value, FALSE);
3510   g_assert (g_variant_get_size (value) == 13);
3511   g_variant_unref (value);
3512   g_assert_cmpstr (string, ==, string2);
3513   g_free (string2);
3514   g_free (string);
3515 }
3516
3517 static void
3518 test_parser (void)
3519 {
3520   TreeInstance *tree;
3521   GVariant *parsed;
3522   GVariant *value;
3523   gchar *pt, *p;
3524   gchar *res;
3525
3526   tree = tree_instance_new (NULL, 3);
3527   value = tree_instance_get_gvariant (tree);
3528   tree_instance_free (tree);
3529
3530   pt = g_variant_print (value, TRUE);
3531   p = g_variant_print (value, FALSE);
3532
3533   parsed = g_variant_parse (NULL, pt, NULL, NULL, NULL);
3534   res = g_variant_print (parsed, FALSE);
3535   g_assert_cmpstr (p, ==, res);
3536   g_variant_unref (parsed);
3537   g_free (res);
3538
3539   parsed = g_variant_parse (g_variant_get_type (value), p,
3540                             NULL, NULL, NULL);
3541   res = g_variant_print (parsed, TRUE);
3542   g_assert_cmpstr (pt, ==, res);
3543   g_variant_unref (parsed);
3544   g_free (res);
3545
3546   g_variant_unref (value);
3547   g_free (pt);
3548   g_free (p);
3549 }
3550
3551 static void
3552 test_parses (void)
3553 {
3554   gint i;
3555
3556   for (i = 0; i < 100; i++)
3557     {
3558       test_parser ();
3559     }
3560
3561   /* mini test */
3562   {
3563     gchar str[256];
3564     GVariant *val;
3565     gchar *p, *p2;
3566
3567     for (i = 0; i < 256; i++)
3568       str[i] = i + 1;
3569
3570     val = g_variant_new_string (str);
3571     p = g_variant_print (val, FALSE);
3572     g_variant_unref (val);
3573
3574     val = g_variant_parse (NULL, p, NULL, NULL, NULL);
3575     p2 = g_variant_print (val, FALSE);
3576
3577     g_assert_cmpstr (str, ==, g_variant_get_string (val, NULL));
3578     g_assert_cmpstr (p, ==, p2);
3579
3580     g_variant_unref (val);
3581     g_free (p2);
3582     g_free (p);
3583   }
3584
3585   /* another mini test */
3586   {
3587     const gchar *end;
3588     GVariant *value;
3589
3590     value = g_variant_parse (G_VARIANT_TYPE_INT32, "1 2 3", NULL, &end, NULL);
3591     g_assert_cmpint (g_variant_get_int32 (value), ==, 1);
3592     /* make sure endptr returning works */
3593     g_assert_cmpstr (end, ==, " 2 3");
3594     g_variant_unref (value);
3595   }
3596
3597   g_variant_type_info_assert_no_infos ();
3598 }
3599
3600 static void
3601 test_parse_failures (void)
3602 {
3603   const gchar *test[] = {
3604     "[1, 2,",                   "6:",              "expected value",
3605     "",                         "0:",              "expected value",
3606     "(1, 2,",                   "6:",              "expected value",
3607     "<1",                       "2:",              "expected `>'",
3608     "[]",                       "0-2:",            "unable to infer",
3609     "(,",                       "1:",              "expected value",
3610     "[4,'']",                   "1-2,3-5:",        "common type",
3611     "[4, '', 5]",               "1-2,4-6:",        "common type",
3612     "['', 4, 5]",               "1-3,5-6:",        "common type",
3613     "[4, 5, '']",               "1-2,7-9:",        "common type",
3614     "[[4], [], ['']]",          "1-4,10-14:",      "common type",
3615     "[[], [4], ['']]",          "5-8,10-14:",      "common type",
3616     "just",                     "4:",              "expected value",
3617     "nothing",                  "0-7:",            "unable to infer",
3618     "just [4, '']",             "6-7,9-11:",       "common type",
3619     "[[4,'']]",                 "2-3,4-6:",        "common type",
3620     "([4,''],)",                "2-3,4-6:",        "common type",
3621     "(4)",                      "2:",              "`,'",
3622     "{}",                       "0-2:",            "unable to infer",
3623     "{[1,2],[3,4]}",            "0-13:",           "basic types",
3624     "{[1,2]:[3,4]}",            "0-13:",           "basic types",
3625     "justt",                    "0-5:",            "unknown keyword",
3626     "nothng",                   "0-6:",            "unknown keyword",
3627     "uint33",                   "0-6:",            "unknown keyword",
3628     "@mi just ''",              "9-11:",           "can not parse as",
3629     "@ai ['']",                 "5-7:",            "can not parse as",
3630     "@(i) ('',)",               "6-8:",            "can not parse as",
3631     "[[], 5]",                  "1-3,5-6:",        "common type",
3632     "[[5], 5]",                 "1-4,6-7:",        "common type",
3633     "5 5",                      "2:",              "expected end of input",
3634     "[5, [5, '']]",             "5-6,8-10:",       "common type",
3635     "@i just 5",                "3-9:",            "can not parse as",
3636     "@i nothing",               "3-10:",           "can not parse as",
3637     "@i []",                    "3-5:",            "can not parse as",
3638     "@i ()",                    "3-5:",            "can not parse as",
3639     "@ai (4,)",                 "4-8:",            "can not parse as",
3640     "@(i) []",                  "5-7:",            "can not parse as",
3641     "(5 5)",                    "3:",              "expected `,'",
3642     "[5 5]",                    "3:",              "expected `,' or `]'",
3643     "(5, 5 5)",                 "6:",              "expected `,' or `)'",
3644     "[5, 5 5]",                 "6:",              "expected `,' or `]'",
3645     "<@i []>",                  "4-6:",            "can not parse as",
3646     "<[5 5]>",                  "4:",              "expected `,' or `]'",
3647     "{[4,''],5}",               "2-3,4-6:",        "common type",
3648     "{5,[4,'']}",               "4-5,6-8:",        "common type",
3649     "@i {1,2}",                 "3-8:",            "can not parse as",
3650     "{@i '', 5}",               "4-6:",            "can not parse as",
3651     "{5, @i ''}",               "7-9:",            "can not parse as",
3652     "@ai {}",                   "4-6:",            "can not parse as",
3653     "{@i '': 5}",               "4-6:",            "can not parse as",
3654     "{5: @i ''}",               "7-9:",            "can not parse as",
3655     "{<4,5}",                   "3:",              "expected `>'",
3656     "{4,<5}",                   "5:",              "expected `>'",
3657     "{4,5,6}",                  "4:",              "expected `}'",
3658     "{5 5}",                    "3:",              "expected `:' or `,'",
3659     "{4: 5: 6}",                "5:",              "expected `,' or `}'",
3660     "{4:5,<6:7}",               "7:",              "expected `>'",
3661     "{4:5,6:<7}",               "9:",              "expected `>'",
3662     "{4:5,6 7}",                "7:",              "expected `:'",
3663     "@o 'foo'",                 "3-8:",            "object path",
3664     "@g 'zzz'",                 "3-8:",            "signature",
3665     "@i true",                  "3-7:",            "can not parse as",
3666     "@z 4",                     "0-2:",            "invalid type",
3667     "@a* []",                   "0-3:",            "definite",
3668     "@ai [3 3]",                "7:",              "expected `,' or `]'",
3669     "18446744073709551616",     "0-20:",           "too big for any type",
3670     "-18446744073709551616",    "0-21:",           "too big for any type",
3671     "byte 256",                 "5-8:",            "out of range for type",
3672     "byte -1",                  "5-7:",            "out of range for type",
3673     "int16 32768",              "6-11:",           "out of range for type",
3674     "int16 -32769",             "6-12:",           "out of range for type",
3675     "uint16 -1",                "7-9:",            "out of range for type",
3676     "uint16 65536",             "7-12:",           "out of range for type",
3677     "2147483648",               "0-10:",           "out of range for type",
3678     "-2147483649",              "0-11:",           "out of range for type",
3679     "uint32 -1",                "7-9:",            "out of range for type",
3680     "uint32 4294967296",        "7-17:",           "out of range for type",
3681     "@x 9223372036854775808",   "3-22:",           "out of range for type",
3682     "@x -9223372036854775809",  "3-23:",           "out of range for type",
3683     "@t -1",                    "3-5:",            "out of range for type",
3684     "@t 18446744073709551616",  "3-23:",           "too big for any type",
3685     "handle 2147483648",        "7-17:",           "out of range for type",
3686     "handle -2147483649",       "7-18:",           "out of range for type",
3687     "1.798e308",                "0-9:",            "too big for any type",
3688     "37.5a488",                 "4-5:",            "invalid character",
3689     "0x7ffgf",                  "5-6:",            "invalid character",
3690     "07758",                    "4-5:",            "invalid character",
3691     "123a5",                    "3-4:",            "invalid character",
3692     "@ai 123",                  "4-7:",            "can not parse as",
3693     "'\"\\'",                   "0-4:",            "unterminated string",
3694     "'\"\\'\\",                 "0-5:",            "unterminated string",
3695     "boolean 4",                "8-9:",            "can not parse as",
3696     "int32 true",               "6-10:",           "can not parse as",
3697     "[double 5, int32 5]",      "1-9,11-18:",      "common type",
3698     "string 4",                 "7-8:",            "can not parse as"
3699   };
3700   gint i;
3701
3702   for (i = 0; i < G_N_ELEMENTS (test); i += 3)
3703     {
3704       GError *error = NULL;
3705       GVariant *value;
3706
3707       value = g_variant_parse (NULL, test[i], NULL, NULL, &error);
3708       g_assert (value == NULL);
3709
3710       if (!strstr (error->message, test[i+2]))
3711         g_error ("test %d: Can't find `%s' in `%s'", i / 3,
3712                  test[i+2], error->message);
3713
3714       if (!g_str_has_prefix (error->message, test[i+1]))
3715         g_error ("test %d: Expected location `%s' in `%s'", i / 3,
3716                  test[i+1], error->message);
3717
3718       g_error_free (error);
3719     }
3720 }
3721
3722 static void
3723 test_parse_positional (void)
3724 {
3725   GVariant *value;
3726   check_and_free (g_variant_new_parsed ("[('one', 1), (%s, 2),"
3727                                         " ('three', %i)]", "two", 3),
3728                   "[('one', 1), ('two', 2), ('three', 3)]");
3729   value = g_variant_new_parsed ("[('one', 1), (%s, 2),"
3730                                 " ('three', %u)]", "two", 3);
3731   g_assert (g_variant_is_of_type (value, G_VARIANT_TYPE ("a(su)")));
3732   check_and_free (value, "[('one', 1), ('two', 2), ('three', 3)]");
3733   check_and_free (g_variant_new_parsed ("{%s:%i}", "one", 1), "{'one': 1}");
3734
3735   if (do_failed_test ("*GVariant format string*"))
3736     {
3737       g_variant_new_parsed ("%z");
3738       abort ();
3739     }
3740
3741   if (do_failed_test ("*can not parse as*"))
3742     {
3743       g_variant_new_parsed ("uint32 %i", 2);
3744       abort ();
3745     }
3746
3747   if (do_failed_test ("*expected GVariant of type `i'*"))
3748     {
3749       g_variant_new_parsed ("%@i", g_variant_new_uint32 (2));
3750       abort ();
3751     }
3752 }
3753
3754 int
3755 main (int argc, char **argv)
3756 {
3757   gint i;
3758
3759   g_test_init (&argc, &argv, NULL);
3760
3761   g_test_add_func ("/gvariant/type", test_gvarianttype);
3762   g_test_add_func ("/gvariant/typeinfo", test_gvarianttypeinfo);
3763   g_test_add_func ("/gvariant/serialiser/maybe", test_maybes);
3764   g_test_add_func ("/gvariant/serialiser/array", test_arrays);
3765   g_test_add_func ("/gvariant/serialiser/tuple", test_tuples);
3766   g_test_add_func ("/gvariant/serialiser/variant", test_variants);
3767   g_test_add_func ("/gvariant/serialiser/strings", test_strings);
3768   g_test_add_func ("/gvariant/serialiser/byteswap", test_byteswaps);
3769
3770   for (i = 1; i <= 20; i += 4)
3771     {
3772       char *testname;
3773
3774       testname = g_strdup_printf ("/gvariant/serialiser/fuzz/%d%%", i);
3775       g_test_add_data_func (testname, GINT_TO_POINTER (i),
3776                             (gpointer) test_fuzzes);
3777       g_free (testname);
3778     }
3779
3780   g_test_add_func ("/gvariant/utf8", test_utf8);
3781   g_test_add_func ("/gvariant/containers", test_containers);
3782   g_test_add_func ("/gvariant/format-strings", test_format_strings);
3783   g_test_add_func ("/gvariant/invalid-varargs", test_invalid_varargs);
3784   g_test_add_func ("/gvariant/varargs", test_varargs);
3785   g_test_add_func ("/gvariant/valist", test_valist);
3786   g_test_add_func ("/gvariant/builder-memory", test_builder_memory);
3787   g_test_add_func ("/gvariant/hashing", test_hashing);
3788   g_test_add_func ("/gvariant/byteswap", test_gv_byteswap);
3789   g_test_add_func ("/gvariant/parser", test_parses);
3790   g_test_add_func ("/gvariant/parse-failures", test_parse_failures);
3791   g_test_add_func ("/gvariant/parse-positional", test_parse_positional);
3792
3793   return g_test_run ();
3794 }