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