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