GVariant: fix string validation
[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_hash (ctype) == g_variant_type_hash (type));
616       g_assert (g_variant_type_is_subtype_of (ctype, type));
617       g_assert (g_variant_type_is_subtype_of (type, ctype));
618
619       /* check if the type is indefinite */
620       if (!g_variant_type_is_definite (type))
621         {
622           struct typestack ts = { type, NULL };
623
624           /* if it is indefinite, then replace one of the indefinite
625            * characters with a matching type and ensure that the result
626            * is a subtype of the original type.  repeat.
627            */
628           subtype_check (type_string->str, &ts);
629         }
630       else
631         /* ensure that no indefinite characters appear */
632         g_assert (strcspn (type_string->str, "r?*") == type_string->len);
633
634
635       /* describe the type.
636        *
637        * exercises the type iterator interface
638        */
639       desc = describe_type (type);
640
641       /* make sure the description matches */
642       g_assert_cmpstr (desc, ==, description->str);
643       g_free (desc);
644
645       /* make an invalid mutation to the type and make sure the type
646        * validation routines catch it */
647       invalid = invalid_mutation (type_string->str);
648       g_assert (g_variant_type_string_is_valid (type_string->str));
649       g_assert (!g_variant_type_string_is_valid (invalid));
650       g_free (invalid);
651
652       /* concatenate another type to the type string and ensure that
653        * the result is recognised as being invalid
654        */
655       other_type = append_type_string (type_string, description, FALSE, 2);
656
657       g_string_free (description, TRUE);
658       g_string_free (type_string, TRUE);
659       g_variant_type_free (other_type);
660       g_variant_type_free (type);
661     }
662 }
663
664 #define ALIGNED(x, y)   (((x + (y - 1)) / y) * y)
665
666 /* do our own calculation of the fixed_size and alignment of a type
667  * using a simple algorithm to make sure the "fancy" one in the
668  * implementation is correct.
669  */
670 static void
671 calculate_type_info (const GVariantType *type,
672                      gsize              *fixed_size,
673                      guint              *alignment)
674 {
675   if (g_variant_type_is_array (type) ||
676       g_variant_type_is_maybe (type))
677     {
678       calculate_type_info (g_variant_type_element (type), NULL, alignment);
679
680       if (fixed_size)
681         *fixed_size = 0;
682     }
683   else if (g_variant_type_is_tuple (type) ||
684            g_variant_type_is_dict_entry (type))
685     {
686       if (g_variant_type_n_items (type))
687         {
688           const GVariantType *sub;
689           gboolean variable;
690           gsize size;
691           guint al;
692
693           variable = FALSE;
694           size = 0;
695           al = 0;
696
697           sub = g_variant_type_first (type);
698           do
699             {
700               gsize this_fs;
701               guint this_al;
702
703               calculate_type_info (sub, &this_fs, &this_al);
704
705               al = MAX (al, this_al);
706
707               if (!this_fs)
708                 {
709                   variable = TRUE;
710                   size = 0;
711                 }
712
713               if (!variable)
714                 {
715                   size = ALIGNED (size, this_al);
716                   size += this_fs;
717                 }
718             }
719           while ((sub = g_variant_type_next (sub)));
720
721           size = ALIGNED (size, al);
722
723           if (alignment)
724             *alignment = al;
725
726           if (fixed_size)
727             *fixed_size = size;
728         }
729       else
730         {
731           if (fixed_size)
732             *fixed_size = 1;
733
734           if (alignment)
735             *alignment = 1;
736         }
737     }
738   else
739     {
740       gint fs, al;
741
742       if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN) ||
743           g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
744         {
745           al = fs = 1;
746         }
747
748       else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT16) ||
749                g_variant_type_equal (type, G_VARIANT_TYPE_UINT16))
750         {
751           al = fs = 2;
752         }
753
754       else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32) ||
755                g_variant_type_equal (type, G_VARIANT_TYPE_UINT32) ||
756                g_variant_type_equal (type, G_VARIANT_TYPE_HANDLE))
757         {
758           al = fs = 4;
759         }
760
761       else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT64) ||
762                g_variant_type_equal (type, G_VARIANT_TYPE_UINT64) ||
763                g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
764         {
765           al = fs = 8;
766         }
767       else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING) ||
768                g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH) ||
769                g_variant_type_equal (type, G_VARIANT_TYPE_SIGNATURE))
770         {
771           al = 1;
772           fs = 0;
773         }
774       else if (g_variant_type_equal (type, G_VARIANT_TYPE_VARIANT))
775         {
776           al = 8;
777           fs = 0;
778         }
779       else
780         g_assert_not_reached ();
781
782       if (fixed_size)
783         *fixed_size = fs;
784
785       if (alignment)
786         *alignment = al;
787     }
788 }
789
790 /* same as the describe_type() function above, but iterates over
791  * typeinfo instead of types.
792  */
793 static gchar *
794 describe_info (GVariantTypeInfo *info)
795 {
796   gchar *result;
797
798   switch (g_variant_type_info_get_type_char (info))
799     {
800     case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
801       {
802         gchar *element;
803
804         element = describe_info (g_variant_type_info_element (info));
805         result = g_strdup_printf ("m of %s", element);
806         g_free (element);
807       }
808       break;
809
810     case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
811       {
812         gchar *element;
813
814         element = describe_info (g_variant_type_info_element (info));
815         result = g_strdup_printf ("a of %s", element);
816         g_free (element);
817       }
818       break;
819
820     case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
821       {
822         const gchar *sep = "";
823         GString *string;
824         gint length;
825         gint i;
826
827         string = g_string_new ("t of [");
828         length = g_variant_type_info_n_members (info);
829
830         for (i = 0; i < length; i++)
831           {
832             const GVariantMemberInfo *minfo;
833             gchar *subtype;
834
835             g_string_append (string, sep);
836             sep = ", ";
837
838             minfo = g_variant_type_info_member_info (info, i);
839             subtype = describe_info (minfo->type_info);
840             g_string_append (string, subtype);
841             g_free (subtype);
842           }
843
844         g_string_append_c (string, ']');
845
846         result = g_string_free (string, FALSE);
847       }
848       break;
849
850     case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
851       {
852         const GVariantMemberInfo *keyinfo, *valueinfo;
853         gchar *key, *value;
854
855         g_assert_cmpint (g_variant_type_info_n_members (info), ==, 2);
856         keyinfo = g_variant_type_info_member_info (info, 0);
857         valueinfo = g_variant_type_info_member_info (info, 1);
858         key = describe_info (keyinfo->type_info);
859         value = describe_info (valueinfo->type_info);
860         result = g_strjoin ("", "e of [", key, ", ", value, "]", NULL);
861         g_free (key);
862         g_free (value);
863       }
864       break;
865
866     case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
867       result = g_strdup ("V");
868       break;
869
870     default:
871       result = g_strdup (g_variant_type_info_get_type_string (info));
872       g_assert_cmpint (strlen (result), ==, 1);
873       break;
874     }
875
876   return result;
877 }
878
879 /* check that the O(1) method of calculating offsets meshes with the
880  * results of simple iteration.
881  */
882 static void
883 check_offsets (GVariantTypeInfo   *info,
884                const GVariantType *type)
885 {
886   gint flavour;
887   gint length;
888
889   length = g_variant_type_info_n_members (info);
890   g_assert_cmpint (length, ==, g_variant_type_n_items (type));
891
892   /* the 'flavour' is the low order bits of the ending point of
893    * variable-size items in the tuple.  this lets us test that the type
894    * info is correct for various starting alignments.
895    */
896   for (flavour = 0; flavour < 8; flavour++)
897     {
898       const GVariantType *subtype;
899       gsize last_offset_index;
900       gsize last_offset;
901       gsize position;
902       gint i;
903
904       subtype = g_variant_type_first (type);
905       last_offset_index = -1;
906       last_offset = 0;
907       position = 0;
908
909       /* go through the tuple, keeping track of our position */
910       for (i = 0; i < length; i++)
911         {
912           gsize fixed_size;
913           guint alignment;
914
915           calculate_type_info (subtype, &fixed_size, &alignment);
916
917           position = ALIGNED (position, alignment);
918
919           /* compare our current aligned position (ie: the start of this
920            * item) to the start offset that would be calculated if we
921            * used the type info
922            */
923           {
924             const GVariantMemberInfo *member;
925             gsize start;
926
927             member = g_variant_type_info_member_info (info, i);
928             g_assert_cmpint (member->i, ==, last_offset_index);
929
930             /* do the calculation using the typeinfo */
931             start = last_offset;
932             start += member->a;
933             start &= member->b;
934             start |= member->c;
935
936             /* did we reach the same spot? */
937             g_assert_cmpint (start, ==, position);
938           }
939
940           if (fixed_size)
941             {
942               /* fixed size.  add that size. */
943               position += fixed_size;
944             }
945           else
946             {
947               /* variable size.  do the flavouring. */
948               while ((position & 0x7) != flavour)
949                 position++;
950
951               /* and store the offset, just like it would be in the
952                * serialised data.
953                */
954               last_offset = position;
955               last_offset_index++;
956             }
957
958           /* next type */
959           subtype = g_variant_type_next (subtype);
960         }
961
962       /* make sure we used up exactly all the types */
963       g_assert (subtype == NULL);
964     }
965 }
966
967 static void
968 test_gvarianttypeinfo (void)
969 {
970   gint i;
971
972   for (i = 0; i < 2000; i++)
973     {
974       GString *type_string, *description;
975       gsize fixed_size1, fixed_size2;
976       guint alignment1, alignment2;
977       GVariantTypeInfo *info;
978       GVariantType *type;
979       gchar *desc;
980
981       type_string = g_string_new (NULL);
982       description = g_string_new (NULL);
983
984       /* random type */
985       type = append_type_string (type_string, description, TRUE, 6);
986
987       /* create a typeinfo for it */
988       info = g_variant_type_info_get (type);
989
990       /* make sure the typeinfo has the right type string */
991       g_assert_cmpstr (g_variant_type_info_get_type_string (info), ==,
992                        type_string->str);
993
994       /* calculate the alignment and fixed size, compare to the
995        * typeinfo's calculations
996        */
997       calculate_type_info (type, &fixed_size1, &alignment1);
998       g_variant_type_info_query (info, &alignment2, &fixed_size2);
999       g_assert_cmpint (fixed_size1, ==, fixed_size2);
1000       g_assert_cmpint (alignment1, ==, alignment2 + 1);
1001
1002       /* test the iteration functions over typeinfo structures by
1003        * "describing" the typeinfo and verifying equality.
1004        */
1005       desc = describe_info (info);
1006       g_assert_cmpstr (desc, ==, description->str);
1007
1008       /* do extra checks for containers */
1009       if (g_variant_type_is_array (type) ||
1010           g_variant_type_is_maybe (type))
1011         {
1012           const GVariantType *element;
1013           gsize efs1, efs2;
1014           guint ea1, ea2;
1015
1016           element = g_variant_type_element (type);
1017           calculate_type_info (element, &efs1, &ea1);
1018           g_variant_type_info_query_element (info, &ea2, &efs2);
1019           g_assert_cmpint (efs1, ==, efs2);
1020           g_assert_cmpint (ea1, ==, ea2 + 1);
1021
1022           g_assert_cmpint (ea1, ==, alignment1);
1023           g_assert_cmpint (0, ==, fixed_size1);
1024         }
1025       else if (g_variant_type_is_tuple (type) ||
1026                g_variant_type_is_dict_entry (type))
1027         {
1028           /* make sure the "magic constants" are working */
1029           check_offsets (info, type);
1030         }
1031
1032       g_string_free (type_string, TRUE);
1033       g_string_free (description, TRUE);
1034       g_variant_type_info_unref (info);
1035       g_variant_type_free (type);
1036       g_free (desc);
1037     }
1038
1039   g_variant_type_info_assert_no_infos ();
1040 }
1041
1042 #define MAX_FIXED_MULTIPLIER    256
1043 #define MAX_INSTANCE_SIZE       1024
1044 #define MAX_ARRAY_CHILDREN      128
1045 #define MAX_TUPLE_CHILDREN      128
1046
1047 /* this function generates a random type such that all characteristics
1048  * that are "interesting" to the serialiser are tested.
1049  *
1050  * this basically means:
1051  *   - test different alignments
1052  *   - test variable sized items and fixed sized items
1053  *   - test different fixed sizes
1054  */
1055 static gchar *
1056 random_type_string (void)
1057 {
1058   const guchar base_types[] = "ynix";
1059   guchar base_type;
1060
1061   base_type = base_types[g_test_rand_int_range (0, 4)];
1062
1063   if (g_test_rand_bit ())
1064     /* construct a fixed-sized type */
1065     {
1066       char type_string[MAX_FIXED_MULTIPLIER];
1067       guint multiplier;
1068       guint i = 0;
1069
1070       multiplier = g_test_rand_int_range (1, sizeof type_string - 1);
1071
1072       type_string[i++] = '(';
1073       while (multiplier--)
1074         type_string[i++] = base_type;
1075       type_string[i++] = ')';
1076
1077       return g_strndup (type_string, i);
1078     }
1079   else
1080     /* construct a variable-sized type */
1081     {
1082       char type_string[2] = { 'a', base_type };
1083
1084       return g_strndup (type_string, 2);
1085     }
1086 }
1087
1088 typedef struct
1089 {
1090   GVariantTypeInfo *type_info;
1091   guint alignment;
1092   gsize size;
1093   gboolean is_fixed_sized;
1094
1095   guint32 seed;
1096
1097 #define INSTANCE_MAGIC    1287582829
1098   guint magic;
1099 } RandomInstance;
1100
1101 static RandomInstance *
1102 random_instance (GVariantTypeInfo *type_info)
1103 {
1104   RandomInstance *instance;
1105
1106   instance = g_slice_new (RandomInstance);
1107
1108   if (type_info == NULL)
1109     {
1110       gchar *str = random_type_string ();
1111       instance->type_info = g_variant_type_info_get (G_VARIANT_TYPE (str));
1112       g_free (str);
1113     }
1114   else
1115     instance->type_info = g_variant_type_info_ref (type_info);
1116
1117   instance->seed = g_test_rand_int ();
1118
1119   g_variant_type_info_query (instance->type_info,
1120                              &instance->alignment,
1121                              &instance->size);
1122
1123   instance->is_fixed_sized = instance->size != 0;
1124
1125   if (!instance->is_fixed_sized)
1126     instance->size = g_test_rand_int_range (0, MAX_INSTANCE_SIZE);
1127
1128   instance->magic = INSTANCE_MAGIC;
1129
1130   return instance;
1131 }
1132
1133 static void
1134 random_instance_free (RandomInstance *instance)
1135 {
1136   g_variant_type_info_unref (instance->type_info);
1137   g_slice_free (RandomInstance, instance);
1138 }
1139
1140 static void
1141 append_instance_size (RandomInstance *instance,
1142                       gsize          *offset)
1143 {
1144   *offset += (-*offset) & instance->alignment;
1145   *offset += instance->size;
1146 }
1147
1148 static void
1149 random_instance_write (RandomInstance *instance,
1150                        guchar         *buffer)
1151 {
1152   GRand *rand;
1153   gint i;
1154
1155   g_assert_cmpint ((gsize) buffer & ALIGN_BITS & instance->alignment, ==, 0);
1156
1157   rand = g_rand_new_with_seed (instance->seed);
1158   for (i = 0; i < instance->size; i++)
1159     buffer[i] = g_rand_int (rand);
1160   g_rand_free (rand);
1161 }
1162
1163 static void
1164 append_instance_data (RandomInstance  *instance,
1165                       guchar         **buffer)
1166 {
1167   while (((gsize) *buffer) & instance->alignment)
1168     *(*buffer)++ = '\0';
1169
1170   random_instance_write (instance, *buffer);
1171   *buffer += instance->size;
1172 }
1173
1174 static gboolean
1175 random_instance_assert (RandomInstance *instance,
1176                         guchar         *buffer,
1177                         gsize           size)
1178 {
1179   GRand *rand;
1180   gint i;
1181
1182   g_assert_cmpint ((gsize) buffer & ALIGN_BITS & instance->alignment, ==, 0);
1183   g_assert_cmpint (size, ==, instance->size);
1184
1185   rand = g_rand_new_with_seed (instance->seed);
1186   for (i = 0; i < instance->size; i++)
1187     {
1188       guchar byte = g_rand_int (rand);
1189
1190       g_assert (buffer[i] == byte);
1191     }
1192   g_rand_free (rand);
1193
1194   return i == instance->size;
1195 }
1196
1197 static gboolean
1198 random_instance_check (RandomInstance *instance,
1199                        guchar         *buffer,
1200                        gsize           size)
1201 {
1202   GRand *rand;
1203   gint i;
1204
1205   g_assert_cmpint ((gsize) buffer & ALIGN_BITS & instance->alignment, ==, 0);
1206
1207   if (size != instance->size)
1208     return FALSE;
1209
1210   rand = g_rand_new_with_seed (instance->seed);
1211   for (i = 0; i < instance->size; i++)
1212     if (buffer[i] != (guchar) g_rand_int (rand))
1213       break;
1214   g_rand_free (rand);
1215
1216   return i == instance->size;
1217 }
1218
1219 static void
1220 random_instance_filler (GVariantSerialised *serialised,
1221                         gpointer            data)
1222 {
1223   RandomInstance *instance = data;
1224
1225   g_assert (instance->magic == INSTANCE_MAGIC);
1226
1227   if (serialised->type_info == NULL)
1228     serialised->type_info = instance->type_info;
1229
1230   if (serialised->size == 0)
1231     serialised->size = instance->size;
1232
1233   g_assert (serialised->type_info == instance->type_info);
1234   g_assert (serialised->size == instance->size);
1235
1236   if (serialised->data)
1237     random_instance_write (instance, serialised->data);
1238 }
1239
1240 static gsize
1241 calculate_offset_size (gsize body_size,
1242                        gsize n_offsets)
1243 {
1244   if (body_size == 0)
1245     return 0;
1246
1247   if (body_size + n_offsets <= G_MAXUINT8)
1248     return 1;
1249
1250   if (body_size + 2 * n_offsets <= G_MAXUINT16)
1251     return 2;
1252
1253   if (body_size + 4 * n_offsets <= G_MAXUINT32)
1254     return 4;
1255
1256   /* the test case won't generate anything bigger */
1257   g_assert_not_reached ();
1258 }
1259
1260 static gpointer
1261 flavoured_malloc (gsize size, gsize flavour)
1262 {
1263   g_assert (flavour < 8);
1264
1265   if (size == 0)
1266     return NULL;
1267
1268   return ((gchar *) g_malloc (size + flavour)) + flavour;
1269 }
1270
1271 static void
1272 flavoured_free (gpointer data,
1273                 gsize flavour)
1274 {
1275   if (!data)
1276     return;
1277   g_free (((gchar *) data) - flavour);
1278 }
1279
1280 static gpointer
1281 align_malloc (gsize size)
1282 {
1283   gpointer mem;
1284
1285 #ifdef HAVE_POSIX_MEMALIGN
1286   if (posix_memalign (&mem, 8, size))
1287     g_error ("posix_memalign failed");
1288 #else
1289   /* NOTE: there may be platforms that lack posix_memalign() and also
1290    * have malloc() that returns non-8-aligned.  if so, we need to try
1291    * harder here.
1292    */
1293   mem = malloc (size);
1294 #endif
1295
1296   return mem;
1297 }
1298
1299 static void
1300 align_free (gpointer mem)
1301 {
1302   free (mem);
1303 }
1304
1305 static void
1306 append_offset (guchar **offset_ptr,
1307                gsize    offset,
1308                guint    offset_size)
1309 {
1310   union
1311   {
1312     guchar bytes[sizeof (gsize)];
1313     gsize integer;
1314   } tmpvalue;
1315
1316   tmpvalue.integer = GSIZE_TO_LE (offset);
1317   memcpy (*offset_ptr, tmpvalue.bytes, offset_size);
1318   *offset_ptr += offset_size;
1319 }
1320
1321 static void
1322 prepend_offset (guchar **offset_ptr,
1323                 gsize    offset,
1324                 guint    offset_size)
1325 {
1326   union
1327   {
1328     guchar bytes[sizeof (gsize)];
1329     gsize integer;
1330   } tmpvalue;
1331
1332   *offset_ptr -= offset_size;
1333   tmpvalue.integer = GSIZE_TO_LE (offset);
1334   memcpy (*offset_ptr, tmpvalue.bytes, offset_size);
1335 }
1336
1337 static void
1338 test_maybe (void)
1339 {
1340   GVariantTypeInfo *type_info;
1341   RandomInstance *instance;
1342   gsize needed_size;
1343   guchar *data;
1344
1345   instance = random_instance (NULL);
1346
1347   {
1348     const gchar *element;
1349     gchar *tmp;
1350
1351     element = g_variant_type_info_get_type_string (instance->type_info);
1352     tmp = g_strdup_printf ("m%s", element);
1353     type_info = g_variant_type_info_get (G_VARIANT_TYPE (tmp));
1354     g_free (tmp);
1355   }
1356
1357   needed_size = g_variant_serialiser_needed_size (type_info,
1358                                                   random_instance_filler,
1359                                                   NULL, 0);
1360   g_assert_cmpint (needed_size, ==, 0);
1361
1362   needed_size = g_variant_serialiser_needed_size (type_info,
1363                                                   random_instance_filler,
1364                                                   (gpointer *) &instance, 1);
1365
1366   if (instance->is_fixed_sized)
1367     g_assert_cmpint (needed_size, ==, instance->size);
1368   else
1369     g_assert_cmpint (needed_size, ==, instance->size + 1);
1370
1371   {
1372     guchar *ptr;
1373
1374     ptr = data = align_malloc (needed_size);
1375     append_instance_data (instance, &ptr);
1376
1377     if (!instance->is_fixed_sized)
1378       *ptr++ = '\0';
1379
1380     g_assert_cmpint (ptr - data, ==, needed_size);
1381   }
1382
1383   {
1384     guint alignment;
1385     guint flavour;
1386
1387     alignment = (instance->alignment & ALIGN_BITS) + 1;
1388
1389     for (flavour = 0; flavour < 8; flavour += alignment)
1390       {
1391         GVariantSerialised serialised;
1392         GVariantSerialised child;
1393
1394         serialised.type_info = type_info;
1395         serialised.data = flavoured_malloc (needed_size, flavour);
1396         serialised.size = needed_size;
1397
1398         g_variant_serialiser_serialise (serialised,
1399                                         random_instance_filler,
1400                                         (gpointer *) &instance, 1);
1401         child = g_variant_serialised_get_child (serialised, 0);
1402         g_assert (child.type_info == instance->type_info);
1403         random_instance_assert (instance, child.data, child.size);
1404         g_variant_type_info_unref (child.type_info);
1405         flavoured_free (serialised.data, flavour);
1406       }
1407   }
1408
1409   g_variant_type_info_unref (type_info);
1410   random_instance_free (instance);
1411   align_free (data);
1412 }
1413
1414 static void
1415 test_maybes (void)
1416 {
1417   guint i;
1418
1419   for (i = 0; i < 1000; i++)
1420     test_maybe ();
1421
1422   g_variant_type_info_assert_no_infos ();
1423 }
1424
1425 static void
1426 test_array (void)
1427 {
1428   GVariantTypeInfo *element_info;
1429   GVariantTypeInfo *array_info;
1430   RandomInstance **instances;
1431   gsize needed_size;
1432   gsize offset_size;
1433   guint n_children;
1434   guchar *data;
1435
1436   {
1437     gchar *element_type, *array_type;
1438
1439     element_type = random_type_string ();
1440     array_type = g_strdup_printf ("a%s", element_type);
1441
1442     element_info = g_variant_type_info_get (G_VARIANT_TYPE (element_type));
1443     array_info = g_variant_type_info_get (G_VARIANT_TYPE (array_type));
1444     g_assert (g_variant_type_info_element (array_info) == element_info);
1445
1446     g_free (element_type);
1447     g_free (array_type);
1448   }
1449
1450   {
1451     guint i;
1452
1453     n_children = g_test_rand_int_range (0, MAX_ARRAY_CHILDREN);
1454     instances = g_new (RandomInstance *, n_children);
1455     for (i = 0; i < n_children; i++)
1456       instances[i] = random_instance (element_info);
1457   }
1458
1459   needed_size = g_variant_serialiser_needed_size (array_info,
1460                                                   random_instance_filler,
1461                                                   (gpointer *) instances,
1462                                                   n_children);
1463
1464   {
1465     gsize element_fixed_size;
1466     gsize body_size = 0;
1467     guint i;
1468
1469     for (i = 0; i < n_children; i++)
1470       append_instance_size (instances[i], &body_size);
1471
1472     g_variant_type_info_query (element_info, NULL, &element_fixed_size);
1473
1474     if (!element_fixed_size)
1475       {
1476         offset_size = calculate_offset_size (body_size, n_children);
1477
1478         if (offset_size == 0)
1479           offset_size = 1;
1480       }
1481     else
1482       offset_size = 0;
1483
1484     g_assert_cmpint (needed_size, ==, body_size + n_children * offset_size);
1485   }
1486
1487   {
1488     guchar *offset_ptr, *body_ptr;
1489     guint i;
1490
1491     body_ptr = data = align_malloc (needed_size);
1492     offset_ptr = body_ptr + needed_size - offset_size * n_children;
1493
1494     for (i = 0; i < n_children; i++)
1495       {
1496         append_instance_data (instances[i], &body_ptr);
1497         append_offset (&offset_ptr, body_ptr - data, offset_size);
1498       }
1499
1500     g_assert (body_ptr == data + needed_size - offset_size * n_children);
1501     g_assert (offset_ptr == data + needed_size);
1502   }
1503
1504   {
1505     guint alignment;
1506     gsize flavour;
1507     guint i;
1508
1509     g_variant_type_info_query (array_info, &alignment, NULL);
1510     alignment = (alignment & ALIGN_BITS) + 1;
1511
1512     for (flavour = 0; flavour < 8; flavour += alignment)
1513       {
1514         GVariantSerialised serialised;
1515
1516         serialised.type_info = array_info;
1517         serialised.data = flavoured_malloc (needed_size, flavour);
1518         serialised.size = needed_size;
1519
1520         g_variant_serialiser_serialise (serialised, random_instance_filler,
1521                                         (gpointer *) instances, n_children);
1522
1523         g_assert (memcmp (serialised.data, data, serialised.size) == 0);
1524         g_assert (g_variant_serialised_n_children (serialised) == n_children);
1525
1526         for (i = 0; i < n_children; i++)
1527           {
1528             GVariantSerialised child;
1529
1530             child = g_variant_serialised_get_child (serialised, i);
1531             g_assert (child.type_info == instances[i]->type_info);
1532             random_instance_assert (instances[i], child.data, child.size);
1533             g_variant_type_info_unref (child.type_info);
1534           }
1535
1536         flavoured_free (serialised.data, flavour);
1537       }
1538   }
1539
1540   {
1541     guint i;
1542
1543     for (i = 0; i < n_children; i++)
1544       random_instance_free (instances[i]);
1545     g_free (instances);
1546   }
1547
1548   g_variant_type_info_unref (element_info);
1549   g_variant_type_info_unref (array_info);
1550   align_free (data);
1551 }
1552
1553 static void
1554 test_arrays (void)
1555 {
1556   guint i;
1557
1558   for (i = 0; i < 100; i++)
1559     test_array ();
1560
1561   g_variant_type_info_assert_no_infos ();
1562 }
1563
1564 static void
1565 test_tuple (void)
1566 {
1567   GVariantTypeInfo *type_info;
1568   RandomInstance **instances;
1569   gboolean fixed_size;
1570   gsize needed_size;
1571   gsize offset_size;
1572   guint n_children;
1573   guint alignment;
1574   guchar *data;
1575
1576   n_children = g_test_rand_int_range (0, MAX_TUPLE_CHILDREN);
1577   instances = g_new (RandomInstance *, n_children);
1578
1579   {
1580     GString *type_string;
1581     guint i;
1582
1583     fixed_size = TRUE;
1584     alignment = 0;
1585
1586     type_string = g_string_new ("(");
1587     for (i = 0; i < n_children; i++)
1588       {
1589         const gchar *str;
1590
1591         instances[i] = random_instance (NULL);
1592
1593         alignment |= instances[i]->alignment;
1594         if (!instances[i]->is_fixed_sized)
1595           fixed_size = FALSE;
1596
1597         str = g_variant_type_info_get_type_string (instances[i]->type_info);
1598         g_string_append (type_string, str);
1599       }
1600     g_string_append_c (type_string, ')');
1601
1602     type_info = g_variant_type_info_get (G_VARIANT_TYPE (type_string->str));
1603     g_string_free (type_string, TRUE);
1604   }
1605
1606   needed_size = g_variant_serialiser_needed_size (type_info,
1607                                                   random_instance_filler,
1608                                                   (gpointer *) instances,
1609                                                   n_children);
1610   {
1611     gsize body_size = 0;
1612     gsize offsets = 0;
1613     guint i;
1614
1615     for (i = 0; i < n_children; i++)
1616       {
1617         append_instance_size (instances[i], &body_size);
1618
1619         if (i != n_children - 1 && !instances[i]->is_fixed_sized)
1620           offsets++;
1621       }
1622
1623     if (fixed_size)
1624       {
1625         body_size += (-body_size) & alignment;
1626
1627         g_assert ((body_size == 0) == (n_children == 0));
1628         if (n_children == 0)
1629           body_size = 1;
1630       }
1631
1632     offset_size = calculate_offset_size (body_size, offsets);
1633     g_assert_cmpint (needed_size, ==, body_size + offsets * offset_size);
1634   }
1635
1636   {
1637     guchar *body_ptr;
1638     guchar *ofs_ptr;
1639     guint i;
1640
1641     body_ptr = data = align_malloc (needed_size);
1642     ofs_ptr = body_ptr + needed_size;
1643
1644     for (i = 0; i < n_children; i++)
1645       {
1646         append_instance_data (instances[i], &body_ptr);
1647
1648         if (i != n_children - 1 && !instances[i]->is_fixed_sized)
1649           prepend_offset (&ofs_ptr, body_ptr - data, offset_size);
1650       }
1651
1652     if (fixed_size)
1653       {
1654         while (((gsize) body_ptr) & alignment)
1655           *body_ptr++ = '\0';
1656
1657         g_assert ((body_ptr == data) == (n_children == 0));
1658         if (n_children == 0)
1659           *body_ptr++ = '\0';
1660
1661       }
1662
1663
1664     g_assert (body_ptr == ofs_ptr);
1665   }
1666
1667   {
1668     gsize flavour;
1669     guint i;
1670
1671     alignment = (alignment & ALIGN_BITS) + 1;
1672
1673     for (flavour = 0; flavour < 8; flavour += alignment)
1674       {
1675         GVariantSerialised serialised;
1676
1677         serialised.type_info = type_info;
1678         serialised.data = flavoured_malloc (needed_size, flavour);
1679         serialised.size = needed_size;
1680
1681         g_variant_serialiser_serialise (serialised, random_instance_filler,
1682                                         (gpointer *) instances, n_children);
1683
1684         g_assert (memcmp (serialised.data, data, serialised.size) == 0);
1685         g_assert (g_variant_serialised_n_children (serialised) == n_children);
1686
1687         for (i = 0; i < n_children; i++)
1688           {
1689             GVariantSerialised child;
1690
1691             child = g_variant_serialised_get_child (serialised, i);
1692             g_assert (child.type_info == instances[i]->type_info);
1693             random_instance_assert (instances[i], child.data, child.size);
1694             g_variant_type_info_unref (child.type_info);
1695           }
1696
1697         flavoured_free (serialised.data, flavour);
1698       }
1699   }
1700
1701   {
1702     guint i;
1703
1704     for (i = 0; i < n_children; i++)
1705       random_instance_free (instances[i]);
1706     g_free (instances);
1707   }
1708
1709   g_variant_type_info_unref (type_info);
1710   align_free (data);
1711 }
1712
1713 static void
1714 test_tuples (void)
1715 {
1716   guint i;
1717
1718   for (i = 0; i < 100; i++)
1719     test_tuple ();
1720
1721   g_variant_type_info_assert_no_infos ();
1722 }
1723
1724 static void
1725 test_variant (void)
1726 {
1727   GVariantTypeInfo *type_info;
1728   RandomInstance *instance;
1729   const gchar *type_string;
1730   gsize needed_size;
1731   guchar *data;
1732   gsize len;
1733
1734   type_info = g_variant_type_info_get (G_VARIANT_TYPE_VARIANT);
1735   instance = random_instance (NULL);
1736
1737   type_string = g_variant_type_info_get_type_string (instance->type_info);
1738   len = strlen (type_string);
1739
1740   needed_size = g_variant_serialiser_needed_size (type_info,
1741                                                   random_instance_filler,
1742                                                   (gpointer *) &instance, 1);
1743
1744   g_assert_cmpint (needed_size, ==, instance->size + 1 + len);
1745
1746   {
1747     guchar *ptr;
1748
1749     ptr = data = align_malloc (needed_size);
1750     append_instance_data (instance, &ptr);
1751     *ptr++ = '\0';
1752     memcpy (ptr, type_string, len);
1753     ptr += len;
1754
1755     g_assert (data + needed_size == ptr);
1756   }
1757
1758   {
1759     gsize alignment;
1760     gsize flavour;
1761
1762     /* variants are always 8-aligned */
1763     alignment = ALIGN_BITS + 1;
1764
1765     for (flavour = 0; flavour < 8; flavour += alignment)
1766       {
1767         GVariantSerialised serialised;
1768         GVariantSerialised child;
1769
1770         serialised.type_info = type_info;
1771         serialised.data = flavoured_malloc (needed_size, flavour);
1772         serialised.size = needed_size;
1773
1774         g_variant_serialiser_serialise (serialised, random_instance_filler,
1775                                         (gpointer *) &instance, 1);
1776
1777         g_assert (memcmp (serialised.data, data, serialised.size) == 0);
1778         g_assert (g_variant_serialised_n_children (serialised) == 1);
1779
1780         child = g_variant_serialised_get_child (serialised, 0);
1781         g_assert (child.type_info == instance->type_info);
1782         random_instance_check (instance, child.data, child.size);
1783
1784         g_variant_type_info_unref (child.type_info);
1785         flavoured_free (serialised.data, flavour);
1786       }
1787   }
1788
1789   g_variant_type_info_unref (type_info);
1790   random_instance_free (instance);
1791   align_free (data);
1792 }
1793
1794 static void
1795 test_variants (void)
1796 {
1797   guint i;
1798
1799   for (i = 0; i < 100; i++)
1800     test_variant ();
1801
1802   g_variant_type_info_assert_no_infos ();
1803 }
1804
1805 static void
1806 test_strings (void)
1807 {
1808   struct {
1809     guint flags;
1810     guint size;
1811     gconstpointer data;
1812   } test_cases[] = {
1813 #define is_nval           0
1814 #define is_string         1
1815 #define is_objpath        is_string | 2
1816 #define is_sig            is_string | 4
1817     { is_sig,       1, "" },
1818     { is_nval,      0, NULL },
1819     { is_nval,     13, "hello\xffworld!" },
1820     { is_string,   13, "hello world!" },
1821     { is_nval,     13, "hello world\0" },
1822     { is_nval,     13, "hello\0world!" },
1823     { is_nval,     12, "hello world!" },
1824     { is_nval,     13, "hello world!\xff" },
1825
1826     { is_objpath,   2, "/" },
1827     { is_objpath,   3, "/a" },
1828     { is_string,    3, "//" },
1829     { is_objpath,  11, "/some/path" },
1830     { is_string,   12, "/some/path/" },
1831     { is_nval,     11, "/some\0path" },
1832     { is_string,   11, "/some\\path" },
1833     { is_string,   12, "/some//path" },
1834     { is_string,   12, "/some-/path" },
1835
1836     { is_sig,       2, "i" },
1837     { is_sig,       2, "s" },
1838     { is_sig,       5, "(si)" },
1839     { is_string,    4, "(si" },
1840     { is_string,    2, "*" },
1841     { is_sig,       3, "ai" },
1842     { is_string,    3, "mi" },
1843     { is_string,    2, "r" },
1844     { is_sig,      15, "(yyy{sv}ssiai)" },
1845     { is_string,   16, "(yyy{yv}ssiai))" },
1846     { is_string,   15, "(yyy{vv}ssiai)" },
1847     { is_string,   15, "(yyy{sv)ssiai}" }
1848   };
1849   guint i;
1850
1851   for (i = 0; i < G_N_ELEMENTS (test_cases); i++)
1852     {
1853       guint flags;
1854
1855       flags = g_variant_serialiser_is_string (test_cases[i].data,
1856                                               test_cases[i].size)
1857         ? 1 : 0;
1858
1859       flags |= g_variant_serialiser_is_object_path (test_cases[i].data,
1860                                                     test_cases[i].size)
1861         ? 2 : 0;
1862
1863       flags |= g_variant_serialiser_is_signature (test_cases[i].data,
1864                                                   test_cases[i].size)
1865         ? 4 : 0;
1866
1867       g_assert (flags == test_cases[i].flags);
1868     }
1869 }
1870
1871 typedef struct _TreeInstance TreeInstance;
1872 struct _TreeInstance
1873 {
1874   GVariantTypeInfo *info;
1875
1876   TreeInstance **children;
1877   gsize n_children;
1878
1879   union {
1880     guint64 integer;
1881     gdouble floating;
1882     gchar string[32];
1883   } data;
1884   gsize data_size;
1885 };
1886
1887 static GVariantType *
1888 make_random_definite_type (int depth)
1889 {
1890   GString *description;
1891   GString *type_string;
1892   GVariantType *type;
1893
1894   description = g_string_new (NULL);
1895   type_string = g_string_new (NULL);
1896   type = append_type_string (type_string, description, TRUE, depth);
1897   g_string_free (description, TRUE);
1898   g_string_free (type_string, TRUE);
1899
1900   return type;
1901 }
1902
1903 static void
1904 make_random_string (gchar              *string,
1905                     gsize               size,
1906                     const GVariantType *type)
1907 {
1908   gint i;
1909
1910   /* create strings that are valid signature strings */
1911 #define good_chars "bynqiuxthdsog"
1912
1913   for (i = 0; i < size - 1; i++)
1914     string[i] = good_chars[g_test_rand_int_range (0, strlen (good_chars))];
1915   string[i] = '\0';
1916
1917   /* in case we need an object path, prefix a '/' */
1918   if (*g_variant_type_peek_string (type) == 'o')
1919     string[0] = '/';
1920
1921 #undef good_chars
1922 }
1923
1924 static TreeInstance *
1925 tree_instance_new (const GVariantType *type,
1926                    int                 depth)
1927 {
1928   const GVariantType *child_type = NULL;
1929   GVariantType *mytype = NULL;
1930   TreeInstance *instance;
1931   gboolean is_tuple_type;
1932
1933   if (type == NULL)
1934     type = mytype = make_random_definite_type (depth);
1935
1936   instance = g_slice_new (TreeInstance);
1937   instance->info = g_variant_type_info_get (type);
1938   instance->children = NULL;
1939   instance->n_children = 0;
1940   instance->data_size = 0;
1941
1942   is_tuple_type = FALSE;
1943
1944   switch (*g_variant_type_peek_string (type))
1945     {
1946     case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
1947       instance->n_children = g_test_rand_int_range (0, 2);
1948       child_type = g_variant_type_element (type);
1949       break;
1950
1951     case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
1952       instance->n_children = g_test_rand_int_range (0, MAX_ARRAY_CHILDREN);
1953       child_type = g_variant_type_element (type);
1954       break;
1955
1956     case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
1957     case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
1958       instance->n_children = g_variant_type_n_items (type);
1959       child_type = g_variant_type_first (type);
1960       is_tuple_type = TRUE;
1961       break;
1962
1963     case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
1964       instance->n_children = 1;
1965       child_type = NULL;
1966       break;
1967
1968     case 'b':
1969       instance->data.integer = g_test_rand_int_range (0, 2);
1970       instance->data_size = 1;
1971       break;
1972
1973     case 'y':
1974       instance->data.integer = g_test_rand_int ();
1975       instance->data_size = 1;
1976       break;
1977
1978     case 'n': case 'q':
1979       instance->data.integer = g_test_rand_int ();
1980       instance->data_size = 2;
1981       break;
1982
1983     case 'i': case 'u': case 'h':
1984       instance->data.integer = g_test_rand_int ();
1985       instance->data_size = 4;
1986       break;
1987
1988     case 'x': case 't':
1989       instance->data.integer = g_test_rand_int ();
1990       instance->data.integer <<= 32;
1991       instance->data.integer |= (guint32) g_test_rand_int ();
1992       instance->data_size = 8;
1993       break;
1994
1995     case 'd':
1996       instance->data.floating = g_test_rand_double ();
1997       instance->data_size = 8;
1998       break;
1999
2000     case 's': case 'o': case 'g':
2001       instance->data_size = g_test_rand_int_range (10, 20);
2002       make_random_string (instance->data.string, instance->data_size, type);
2003       break;
2004     }
2005
2006   if (instance->data_size == 0)
2007     /* no data -> it is a container */
2008     {
2009       guint i;
2010
2011       instance->children = g_new (TreeInstance *, instance->n_children);
2012
2013       for (i = 0; i < instance->n_children; i++)
2014         {
2015           instance->children[i] = tree_instance_new (child_type, depth - 1);
2016
2017           if (is_tuple_type)
2018             child_type = g_variant_type_next (child_type);
2019         }
2020
2021       g_assert (!is_tuple_type || child_type == NULL);
2022     }
2023
2024   g_variant_type_free (mytype);
2025
2026   return instance;
2027 }
2028
2029 static void
2030 tree_instance_free (TreeInstance *instance)
2031 {
2032   gint i;
2033
2034   g_variant_type_info_unref (instance->info);
2035   for (i = 0; i < instance->n_children; i++)
2036     tree_instance_free (instance->children[i]);
2037   g_free (instance->children);
2038   g_slice_free (TreeInstance, instance);
2039 }
2040
2041 static gboolean i_am_writing_byteswapped;
2042
2043 static void
2044 tree_filler (GVariantSerialised *serialised,
2045              gpointer            data)
2046 {
2047   TreeInstance *instance = data;
2048
2049   if (serialised->type_info == NULL)
2050     serialised->type_info = instance->info;
2051
2052   if (instance->data_size == 0)
2053     /* is a container */
2054     {
2055       if (serialised->size == 0)
2056         serialised->size =
2057           g_variant_serialiser_needed_size (instance->info, tree_filler,
2058                                             (gpointer *) instance->children,
2059                                             instance->n_children);
2060
2061       if (serialised->data)
2062         g_variant_serialiser_serialise (*serialised, tree_filler,
2063                                         (gpointer *) instance->children,
2064                                         instance->n_children);
2065     }
2066   else
2067     /* it is a leaf */
2068     {
2069       if (serialised->size == 0)
2070         serialised->size = instance->data_size;
2071
2072       if (serialised->data)
2073         {
2074           switch (instance->data_size)
2075             {
2076             case 1:
2077               *serialised->data = instance->data.integer;
2078               break;
2079
2080             case 2:
2081               {
2082                 guint16 value = instance->data.integer;
2083
2084                 if (i_am_writing_byteswapped)
2085                   value = GUINT16_SWAP_LE_BE (value);
2086
2087                 *(guint16 *) serialised->data = value;
2088               }
2089               break;
2090
2091             case 4:
2092               {
2093                 guint32 value = instance->data.integer;
2094
2095                 if (i_am_writing_byteswapped)
2096                   value = GUINT32_SWAP_LE_BE (value);
2097
2098                 *(guint32 *) serialised->data = value;
2099               }
2100               break;
2101
2102             case 8:
2103               {
2104                 guint64 value = instance->data.integer;
2105
2106                 if (i_am_writing_byteswapped)
2107                   value = GUINT64_SWAP_LE_BE (value);
2108
2109                 *(guint64 *) serialised->data = value;
2110               }
2111               break;
2112
2113             default:
2114               memcpy (serialised->data,
2115                       instance->data.string,
2116                       instance->data_size);
2117               break;
2118             }
2119         }
2120     }
2121 }
2122
2123 static gboolean
2124 check_tree (TreeInstance       *instance,
2125             GVariantSerialised  serialised)
2126 {
2127   if (instance->info != serialised.type_info)
2128     return FALSE;
2129
2130   if (instance->data_size == 0)
2131     /* is a container */
2132     {
2133       gint i;
2134
2135       if (g_variant_serialised_n_children (serialised) !=
2136           instance->n_children)
2137         return FALSE;
2138
2139       for (i = 0; i < instance->n_children; i++)
2140         {
2141           GVariantSerialised child;
2142           gpointer data = NULL;
2143           gboolean ok;
2144
2145           child = g_variant_serialised_get_child (serialised, i);
2146           if (child.size && child.data == NULL)
2147             child.data = data = g_malloc0 (child.size);
2148           ok = check_tree (instance->children[i], child);
2149           g_variant_type_info_unref (child.type_info);
2150           g_free (data);
2151
2152           if (!ok)
2153             return FALSE;
2154         }
2155
2156       return TRUE;
2157     }
2158   else
2159     /* it is a leaf */
2160     {
2161       switch (instance->data_size)
2162         {
2163         case 1:
2164           g_assert (serialised.size == 1);
2165           return *(guint8 *) serialised.data ==
2166                   (guint8) instance->data.integer;
2167
2168         case 2:
2169           g_assert (serialised.size == 2);
2170           return *(guint16 *) serialised.data ==
2171                   (guint16) instance->data.integer;
2172
2173         case 4:
2174           g_assert (serialised.size == 4);
2175           return *(guint32 *) serialised.data ==
2176                   (guint32) instance->data.integer;
2177
2178         case 8:
2179           g_assert (serialised.size == 8);
2180           return *(guint64 *) serialised.data ==
2181                   (guint64) instance->data.integer;
2182
2183         default:
2184           if (serialised.size != instance->data_size)
2185             return FALSE;
2186
2187           return memcmp (serialised.data,
2188                          instance->data.string,
2189                          instance->data_size) == 0;
2190         }
2191     }
2192 }
2193
2194 static void
2195 serialise_tree (TreeInstance       *tree,
2196                 GVariantSerialised *serialised)
2197 {
2198   GVariantSerialised empty = {  };
2199
2200   *serialised = empty;
2201   tree_filler (serialised, tree);
2202   serialised->data = g_malloc (serialised->size);
2203   tree_filler (serialised, tree);
2204 }
2205
2206 static void
2207 test_byteswap (void)
2208 {
2209   GVariantSerialised one, two;
2210   TreeInstance *tree;
2211
2212   tree = tree_instance_new (NULL, 3);
2213   serialise_tree (tree, &one);
2214
2215   i_am_writing_byteswapped = TRUE;
2216   serialise_tree (tree, &two);
2217   i_am_writing_byteswapped = FALSE;
2218
2219   g_variant_serialised_byteswap (two);
2220
2221   g_assert_cmpint (one.size, ==, two.size);
2222   g_assert (memcmp (one.data, two.data, one.size) == 0);
2223
2224   tree_instance_free (tree);
2225   g_free (one.data);
2226   g_free (two.data);
2227 }
2228
2229 static void
2230 test_byteswaps (void)
2231 {
2232   int i;
2233
2234   for (i = 0; i < 200; i++)
2235     test_byteswap ();
2236
2237   g_variant_type_info_assert_no_infos ();
2238 }
2239
2240 static void
2241 test_fuzz (gdouble *fuzziness)
2242 {
2243   GVariantSerialised serialised;
2244   TreeInstance *tree;
2245
2246   /* make an instance */
2247   tree = tree_instance_new (NULL, 3);
2248
2249   /* serialise it */
2250   serialise_tree (tree, &serialised);
2251
2252   g_assert (g_variant_serialised_is_normal (serialised));
2253   g_assert (check_tree (tree, serialised));
2254
2255   if (serialised.size)
2256     {
2257       gboolean fuzzed = FALSE;
2258       gboolean a, b;
2259
2260       while (!fuzzed)
2261         {
2262           gint i;
2263
2264           for (i = 0; i < serialised.size; i++)
2265             if (randomly (*fuzziness))
2266               {
2267                 serialised.data[i] += g_test_rand_int_range (1, 256);
2268                 fuzzed = TRUE;
2269               }
2270         }
2271
2272       /* at least one byte in the serialised data has changed.
2273        *
2274        * this means that at least one of the following is true:
2275        *
2276        *    - the serialised data now represents a different value:
2277        *        check_tree() will return FALSE
2278        *
2279        *    - the serialised data is in non-normal form:
2280        *        g_variant_serialiser_is_normal() will return FALSE
2281        *
2282        * we always do both checks to increase exposure of the serialiser
2283        * to corrupt data.
2284        */
2285       a = g_variant_serialised_is_normal (serialised);
2286       b = check_tree (tree, serialised);
2287
2288       g_assert (!a || !b);
2289     }
2290
2291   tree_instance_free (tree);
2292   g_free (serialised.data);
2293 }
2294
2295
2296 static void
2297 test_fuzzes (gpointer data)
2298 {
2299   gdouble fuzziness;
2300   int i;
2301
2302   fuzziness = GPOINTER_TO_INT (data) / 100.;
2303
2304   for (i = 0; i < 200; i++)
2305     test_fuzz (&fuzziness);
2306
2307   g_variant_type_info_assert_no_infos ();
2308 }
2309
2310 static GVariant *
2311 tree_instance_get_gvariant (TreeInstance *tree)
2312 {
2313   const GVariantType *type;
2314   GVariant *result;
2315
2316   type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
2317
2318   switch (g_variant_type_info_get_type_char (tree->info))
2319     {
2320     case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
2321       {
2322         const GVariantType *child_type;
2323         GVariant *child;
2324
2325         if (tree->n_children)
2326           child = tree_instance_get_gvariant (tree->children[0]);
2327         else
2328           child = NULL;
2329
2330         child_type = g_variant_type_element (type);
2331
2332         if (child != NULL && randomly (0.5))
2333           child_type = NULL;
2334
2335         result = g_variant_new_maybe (child_type, child);
2336       }
2337       break;
2338
2339     case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
2340       {
2341         const GVariantType *child_type;
2342         GVariant **children;
2343         gint i;
2344
2345         children = g_new (GVariant *, tree->n_children);
2346         for (i = 0; i < tree->n_children; i++)
2347           children[i] = tree_instance_get_gvariant (tree->children[i]);
2348
2349         child_type = g_variant_type_element (type);
2350
2351         if (i > 0 && randomly (0.5))
2352           child_type = NULL;
2353
2354         result = g_variant_new_array (child_type, children, tree->n_children);
2355         g_free (children);
2356       }
2357       break;
2358
2359     case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
2360       {
2361         GVariant **children;
2362         gint i;
2363
2364         children = g_new (GVariant *, tree->n_children);
2365         for (i = 0; i < tree->n_children; i++)
2366           children[i] = tree_instance_get_gvariant (tree->children[i]);
2367
2368         result = g_variant_new_tuple (children, tree->n_children);
2369         g_free (children);
2370       }
2371       break;
2372
2373     case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
2374       {
2375         GVariant *key, *val;
2376
2377         g_assert (tree->n_children == 2);
2378
2379         key = tree_instance_get_gvariant (tree->children[0]);
2380         val = tree_instance_get_gvariant (tree->children[1]);
2381
2382         result = g_variant_new_dict_entry (key, val);
2383       }
2384       break;
2385
2386     case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
2387       {
2388         GVariant *value;
2389
2390         g_assert (tree->n_children == 1);
2391
2392         value = tree_instance_get_gvariant (tree->children[0]);
2393         result = g_variant_new_variant (value);
2394       }
2395       break;
2396
2397     case 'b':
2398       result = g_variant_new_boolean (tree->data.integer > 0);
2399       break;
2400
2401     case 'y':
2402       result = g_variant_new_byte (tree->data.integer);
2403       break;
2404
2405     case 'n':
2406       result = g_variant_new_int16 (tree->data.integer);
2407       break;
2408
2409     case 'q':
2410       result = g_variant_new_uint16 (tree->data.integer);
2411       break;
2412
2413     case 'i':
2414       result = g_variant_new_int32 (tree->data.integer);
2415       break;
2416
2417     case 'u':
2418       result = g_variant_new_uint32 (tree->data.integer);
2419       break;
2420
2421     case 'x':
2422       result = g_variant_new_int64 (tree->data.integer);
2423       break;
2424
2425     case 't':
2426       result = g_variant_new_uint64 (tree->data.integer);
2427       break;
2428
2429     case 'h':
2430       result = g_variant_new_handle (tree->data.integer);
2431       break;
2432
2433     case 'd':
2434       result = g_variant_new_double (tree->data.floating);
2435       break;
2436
2437     case 's':
2438       result = g_variant_new_string (tree->data.string);
2439       break;
2440
2441     case 'o':
2442       result = g_variant_new_object_path (tree->data.string);
2443       break;
2444
2445     case 'g':
2446       result = g_variant_new_signature (tree->data.string);
2447       break;
2448
2449     default:
2450       g_assert_not_reached ();
2451     }
2452
2453   return result;
2454 }
2455
2456 static gboolean
2457 tree_instance_check_gvariant (TreeInstance *tree,
2458                               GVariant     *value)
2459 {
2460   const GVariantType *type;
2461
2462   type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
2463   g_assert (g_variant_is_of_type (value, type));
2464
2465   switch (g_variant_type_info_get_type_char (tree->info))
2466     {
2467     case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
2468       {
2469         GVariant *child;
2470         gboolean equal;
2471
2472         child = g_variant_get_maybe (value);
2473
2474         if (child != NULL && tree->n_children == 1)
2475           equal = tree_instance_check_gvariant (tree->children[0], child);
2476         else if (child == NULL && tree->n_children == 0)
2477           equal = TRUE;
2478         else
2479           equal = FALSE;
2480
2481         if (child != NULL)
2482           g_variant_unref (child);
2483
2484         return equal;
2485       }
2486       break;
2487
2488     case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
2489     case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
2490     case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
2491       {
2492         gsize i;
2493
2494         if (g_variant_n_children (value) != tree->n_children)
2495           return FALSE;
2496
2497         for (i = 0; i < tree->n_children; i++)
2498           {
2499             GVariant *child;
2500             gboolean equal;
2501
2502             child = g_variant_get_child_value (value, i);
2503             equal = tree_instance_check_gvariant (tree->children[i], child);
2504             g_variant_unref (child);
2505
2506             if (!equal)
2507               return FALSE;
2508           }
2509
2510         return TRUE;
2511       }
2512       break;
2513
2514     case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
2515       {
2516         const gchar *str1, *str2;
2517         GVariant *child;
2518         gboolean equal;
2519
2520         child = g_variant_get_variant (value);
2521         str1 = g_variant_get_type_string (child);
2522         str2 = g_variant_type_info_get_type_string (tree->children[0]->info);
2523         /* GVariant only keeps one copy of type strings around */
2524         equal = str1 == str2 &&
2525                 tree_instance_check_gvariant (tree->children[0], child);
2526
2527         g_variant_unref (child);
2528
2529         return equal;
2530       }
2531       break;
2532
2533     case 'b':
2534       return g_variant_get_boolean (value) == tree->data.integer;
2535
2536     case 'y':
2537       return g_variant_get_byte (value) == (guchar) tree->data.integer;
2538
2539     case 'n':
2540       return g_variant_get_int16 (value) == (gint16) tree->data.integer;
2541
2542     case 'q':
2543       return g_variant_get_uint16 (value) == (guint16) tree->data.integer;
2544
2545     case 'i':
2546       return g_variant_get_int32 (value) == (gint32) tree->data.integer;
2547
2548     case 'u':
2549       return g_variant_get_uint32 (value) == (guint32) tree->data.integer;
2550
2551     case 'x':
2552       return g_variant_get_int64 (value) == (gint64) tree->data.integer;
2553
2554     case 't':
2555       return g_variant_get_uint64 (value) == (guint64) tree->data.integer;
2556
2557     case 'h':
2558       return g_variant_get_handle (value) == (gint32) tree->data.integer;
2559
2560     case 'd':
2561       {
2562         gdouble floating = g_variant_get_double (value);
2563
2564         return memcmp (&floating, &tree->data.floating, sizeof floating) == 0;
2565       }
2566
2567     case 's':
2568     case 'o':
2569     case 'g':
2570       return strcmp (g_variant_get_string (value, NULL),
2571                      tree->data.string) == 0;
2572
2573     default:
2574       g_assert_not_reached ();
2575     }
2576 }
2577
2578 static void
2579 tree_instance_build_gvariant (TreeInstance    *tree,
2580                               GVariantBuilder *builder,
2581                               gboolean         guess_ok)
2582 {
2583   const GVariantType *type;
2584
2585   type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
2586
2587   if (g_variant_type_is_container (type))
2588     {
2589       gsize i;
2590
2591       /* force GVariantBuilder to guess the type half the time */
2592       if (guess_ok && randomly (0.5))
2593         {
2594           if (g_variant_type_is_array (type) && tree->n_children)
2595             type = G_VARIANT_TYPE_ARRAY;
2596
2597           if (g_variant_type_is_maybe (type) && tree->n_children)
2598             type = G_VARIANT_TYPE_MAYBE;
2599
2600           if (g_variant_type_is_tuple (type))
2601             type = G_VARIANT_TYPE_TUPLE;
2602
2603           if (g_variant_type_is_dict_entry (type))
2604             type = G_VARIANT_TYPE_DICT_ENTRY;
2605         }
2606       else
2607         guess_ok = FALSE;
2608
2609       g_variant_builder_open (builder, type);
2610
2611       for (i = 0; i < tree->n_children; i++)
2612         tree_instance_build_gvariant (tree->children[i], builder, guess_ok);
2613
2614       g_variant_builder_close (builder);
2615     }
2616   else
2617     g_variant_builder_add_value (builder, tree_instance_get_gvariant (tree));
2618 }
2619
2620
2621 static gboolean
2622 tree_instance_check_iter (TreeInstance *tree,
2623                           GVariantIter *iter)
2624 {
2625   GVariant *value;
2626
2627   value = g_variant_iter_next_value (iter);
2628
2629   if (g_variant_is_container (value))
2630     {
2631       gsize i;
2632
2633       iter = g_variant_iter_new (value);
2634       g_variant_unref (value);
2635
2636       if (g_variant_iter_n_children (iter) != tree->n_children)
2637         {
2638           g_variant_iter_free (iter);
2639           return FALSE;
2640         }
2641
2642       for (i = 0; i < tree->n_children; i++)
2643         if (!tree_instance_check_iter (tree->children[i], iter))
2644           {
2645             g_variant_iter_free (iter);
2646             return FALSE;
2647           }
2648
2649       g_assert (g_variant_iter_next_value (iter) == NULL);
2650       g_variant_iter_free (iter);
2651
2652       return TRUE;
2653     }
2654
2655   else
2656     {
2657       gboolean equal;
2658
2659       equal = tree_instance_check_gvariant (tree, value);
2660       g_variant_unref (value);
2661
2662       return equal;
2663     }
2664 }
2665
2666 static void
2667 test_container (void)
2668 {
2669   TreeInstance *tree;
2670   GVariant *value;
2671   gchar *s1, *s2;
2672
2673   tree = tree_instance_new (NULL, 3);
2674   value = g_variant_ref_sink (tree_instance_get_gvariant (tree));
2675
2676   s1 = g_variant_print (value, TRUE);
2677   g_assert (tree_instance_check_gvariant (tree, value));
2678
2679   g_variant_get_data (value);
2680
2681   s2 = g_variant_print (value, TRUE);
2682   g_assert (tree_instance_check_gvariant (tree, value));
2683
2684   g_assert_cmpstr (s1, ==, s2);
2685
2686   if (g_variant_is_container (value))
2687     {
2688       GVariantBuilder builder;
2689       GVariantIter iter;
2690       GVariant *built;
2691       GVariant *val;
2692       gchar *s3;
2693
2694       g_variant_builder_init (&builder, G_VARIANT_TYPE_VARIANT);
2695       tree_instance_build_gvariant (tree, &builder, TRUE);
2696       built = g_variant_builder_end (&builder);
2697       g_variant_ref_sink (built);
2698       g_variant_get_data (built);
2699       val = g_variant_get_variant (built);
2700
2701       s3 = g_variant_print (val, TRUE);
2702       g_assert_cmpstr (s1, ==, s3);
2703
2704       g_variant_iter_init (&iter, built);
2705       g_assert (tree_instance_check_iter (tree, &iter));
2706       g_assert (g_variant_iter_next_value (&iter) == NULL);
2707
2708       g_variant_unref (built);
2709       g_variant_unref (val);
2710       g_free (s3);
2711     }
2712
2713   tree_instance_free (tree);
2714   g_variant_unref (value);
2715   g_free (s2);
2716   g_free (s1);
2717 }
2718
2719 static void
2720 test_utf8 (void)
2721 {
2722   const gchar invalid[] = "hello\xffworld";
2723   GVariant *value;
2724
2725   /* ensure that the test data is not valid utf8... */
2726   g_assert (!g_utf8_validate (invalid, -1, NULL));
2727
2728   /* load the data untrusted */
2729   value = g_variant_new_from_data (G_VARIANT_TYPE_STRING,
2730                                    invalid, sizeof invalid,
2731                                    FALSE, NULL, NULL);
2732
2733   /* ensure that the problem is caught and we get valid UTF-8 */
2734   g_assert (g_utf8_validate (g_variant_get_string (value, NULL), -1, NULL));
2735   g_variant_unref (value);
2736
2737
2738   /* now load it trusted */
2739   value = g_variant_new_from_data (G_VARIANT_TYPE_STRING,
2740                                    invalid, sizeof invalid,
2741                                    TRUE, NULL, NULL);
2742
2743   /* ensure we get the invalid data (ie: make sure that time wasn't
2744    * wasted on validating data that was marked as trusted)
2745    */
2746   g_assert (g_variant_get_string (value, NULL) == invalid);
2747   g_variant_unref (value);
2748 }
2749
2750 static void
2751 test_containers (void)
2752 {
2753   gint i;
2754
2755   for (i = 0; i < 100; i++)
2756     {
2757       test_container ();
2758     }
2759
2760   g_variant_type_info_assert_no_infos ();
2761 }
2762
2763 static void
2764 test_format_strings (void)
2765 {
2766   GVariantType *type;
2767   const gchar *end;
2768
2769   g_assert (g_variant_format_string_scan ("i", NULL, &end) && *end == '\0');
2770   g_assert (g_variant_format_string_scan ("@i", NULL, &end) && *end == '\0');
2771   g_assert (g_variant_format_string_scan ("@ii", NULL, &end) && *end == 'i');
2772   g_assert (g_variant_format_string_scan ("^a&s", NULL, &end) && *end == '\0');
2773   g_assert (g_variant_format_string_scan ("(^as)", NULL, &end) &&
2774             *end == '\0');
2775   g_assert (!g_variant_format_string_scan ("(^s)", NULL, &end));
2776   g_assert (!g_variant_format_string_scan ("(^a)", NULL, &end));
2777   g_assert (!g_variant_format_string_scan ("(z)", NULL, &end));
2778   g_assert (!g_variant_format_string_scan ("az", NULL, &end));
2779   g_assert (!g_variant_format_string_scan ("{**}", NULL, &end));
2780   g_assert (!g_variant_format_string_scan ("{@**}", NULL, &end));
2781   g_assert (g_variant_format_string_scan ("{@y*}", NULL, &end) &&
2782             *end == '\0');
2783   g_assert (g_variant_format_string_scan ("{yv}", NULL, &end) &&
2784             *end == '\0');
2785   g_assert (!g_variant_format_string_scan ("{&?v}", NULL, &end));
2786   g_assert (g_variant_format_string_scan ("{@?v}", NULL, &end) &&
2787             *end == '\0');
2788   g_assert (!g_variant_format_string_scan ("{&@sv}", NULL, &end));
2789   g_assert (!g_variant_format_string_scan ("{@&sv}", NULL, &end));
2790   g_assert (g_variant_format_string_scan ("{&sv}", NULL, &end) &&
2791             *end == '\0');
2792   g_assert (!g_variant_format_string_scan ("{vv}", NULL, &end));
2793   g_assert (!g_variant_format_string_scan ("{y}", NULL, &end));
2794   g_assert (!g_variant_format_string_scan ("{yyy}", NULL, &end));
2795   g_assert (!g_variant_format_string_scan ("{ya}", NULL, &end));
2796   g_assert (g_variant_format_string_scan ("&s", NULL, &end) && *end == '\0');
2797   g_assert (!g_variant_format_string_scan ("&as", NULL, &end));
2798   g_assert (!g_variant_format_string_scan ("@z", NULL, &end));
2799   g_assert (!g_variant_format_string_scan ("az", NULL, &end));
2800   g_assert (!g_variant_format_string_scan ("a&s", NULL, &end));
2801
2802   type = g_variant_format_string_scan_type ("mm(@xy^a&s*?@?)", NULL, &end);
2803   g_assert (type && *end == '\0');
2804   g_assert (g_variant_type_equal (type, G_VARIANT_TYPE ("mm(xyas*?\?)")));
2805   g_variant_type_free (type);
2806
2807   type = g_variant_format_string_scan_type ("mm(@xy^a&*?@?)", NULL, NULL);
2808   g_assert (type == NULL);
2809 }
2810
2811 static void
2812 exit_on_abort (int signal)
2813 {
2814   exit (signal);
2815 }
2816
2817 static gboolean
2818 do_failed_test (const gchar *pattern)
2819 {
2820   if (g_test_trap_fork (1000000, G_TEST_TRAP_SILENCE_STDERR))
2821     {
2822       signal (SIGABRT, exit_on_abort);
2823       return TRUE;
2824     }
2825
2826   g_test_trap_assert_failed ();
2827   g_test_trap_assert_stderr (pattern);
2828
2829   return FALSE;
2830 }
2831
2832 static void
2833 test_invalid_varargs (void)
2834 {
2835   if (!g_test_undefined ())
2836     return;
2837
2838   if (do_failed_test ("*GVariant format string*"))
2839     {
2840       g_variant_new ("z");
2841       abort ();
2842     }
2843
2844   if (do_failed_test ("*valid GVariant format string as a prefix*"))
2845     {
2846       const gchar *end;
2847
2848       g_variant_new_va ("z", &end, NULL);
2849       abort ();
2850     }
2851
2852   if (do_failed_test ("*type of `q' but * has a type of `y'*"))
2853     {
2854       g_variant_get (g_variant_new ("y", 'a'), "q");
2855       abort ();
2856     }
2857 }
2858
2859 static void
2860 check_and_free (GVariant    *value,
2861                 const gchar *str)
2862 {
2863   gchar *valstr = g_variant_print (value, FALSE);
2864   g_assert_cmpstr (str, ==, valstr);
2865   g_variant_unref (value);
2866   g_free (valstr);
2867 }
2868
2869 static void
2870 test_varargs (void)
2871 {
2872   {
2873     GVariantBuilder array;
2874
2875     g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
2876     g_variant_builder_add_parsed (&array, "{'size', <(%i, %i)> }", 800, 600);
2877     g_variant_builder_add (&array, "{sv}", "title",
2878                            g_variant_new_string ("Test case"));
2879     g_variant_builder_add_value (&array,
2880       g_variant_new_dict_entry (g_variant_new_string ("temperature"),
2881                                 g_variant_new_variant (
2882                                   g_variant_new_double (37.5))));
2883     check_and_free (g_variant_new ("(ma{sv}m(a{sv})ma{sv}ii)",
2884                                    NULL, FALSE, NULL, &array, 7777, 8888),
2885                     "(nothing, nothing, {'size': <(800, 600)>, "
2886                                         "'title': <'Test case'>, "
2887                                         "'temperature': <37.5>}, "
2888                      "7777, 8888)");
2889
2890     check_and_free (g_variant_new ("(imimimmimmimmi)",
2891                                    123,
2892                                    FALSE, 321,
2893                                    TRUE, 123,
2894                                    FALSE, TRUE, 321,
2895                                    TRUE, FALSE, 321,
2896                                    TRUE, TRUE, 123),
2897                     "(123, nothing, 123, nothing, just nothing, 123)");
2898
2899     check_and_free (g_variant_new ("(ybnixd)",
2900                                    'a', 1, 22, 33, (guint64) 44, 5.5),
2901                     "(0x61, true, 22, 33, 44, 5.5)");
2902
2903     check_and_free (g_variant_new ("(@y?*rv)",
2904                                    g_variant_new ("y", 'a'),
2905                                    g_variant_new ("y", 'b'),
2906                                    g_variant_new ("y", 'c'),
2907                                    g_variant_new ("(y)", 'd'),
2908                                    g_variant_new ("y", 'e')),
2909                     "(0x61, 0x62, 0x63, (0x64,), <byte 0x65>)");
2910   }
2911
2912   {
2913     GVariantBuilder array;
2914     GVariantIter iter;
2915     GVariant *value;
2916     gchar *number;
2917     gboolean just;
2918     gint i, val;
2919
2920     g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
2921     for (i = 0; i < 100; i++)
2922       {
2923         number = g_strdup_printf ("%d", i);
2924         g_variant_builder_add (&array, "s", number);
2925         g_free (number);
2926       }
2927
2928     value = g_variant_builder_end (&array);
2929     g_variant_iter_init (&iter, value);
2930
2931     i = 0;
2932     while (g_variant_iter_loop (&iter, "s", &number))
2933       {
2934         gchar *check = g_strdup_printf ("%d", i++);
2935         g_assert_cmpstr (number, ==, check);
2936         g_free (check);
2937       }
2938     g_assert (number == NULL);
2939     g_assert (i == 100);
2940
2941     g_variant_unref (value);
2942
2943     g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
2944     for (i = 0; i < 100; i++)
2945       g_variant_builder_add (&array, "mi", i % 2 == 0, i);
2946     value = g_variant_builder_end (&array);
2947
2948     i = 0;
2949     g_variant_iter_init (&iter, value);
2950     while (g_variant_iter_loop (&iter, "mi", NULL, &val))
2951       g_assert (val == i++ || val == 0);
2952     g_assert (i == 100);
2953
2954     i = 0;
2955     g_variant_iter_init (&iter, value);
2956     while (g_variant_iter_loop (&iter, "mi", &just, &val))
2957       {
2958         gint this = i++;
2959
2960         if (this % 2 == 0)
2961           {
2962             g_assert (just);
2963             g_assert (val == this);
2964           }
2965         else
2966           {
2967             g_assert (!just);
2968             g_assert (val == 0);
2969           }
2970       }
2971     g_assert (i == 100);
2972
2973     g_variant_unref (value);
2974   }
2975
2976   {
2977     const gchar *strvector[] = {"/hello", "/world", NULL};
2978     const gchar *test_strs[] = {"/foo", "/bar", "/baz" };
2979     GVariantBuilder builder;
2980     GVariantIter *array;
2981     GVariantIter tuple;
2982     const gchar **strv;
2983     gchar **my_strv;
2984     GVariant *value;
2985     gchar *str;
2986     gint i;
2987
2988     g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
2989     g_variant_builder_add (&builder, "s", "/foo");
2990     g_variant_builder_add (&builder, "s", "/bar");
2991     g_variant_builder_add (&builder, "s", "/baz");
2992     value = g_variant_new("(as^as^a&s)", &builder, strvector, strvector);
2993     g_variant_iter_init (&tuple, value);
2994     g_variant_iter_next (&tuple, "as", &array);
2995
2996     i = 0;
2997     while (g_variant_iter_loop (array, "s", &str))
2998       g_assert_cmpstr (str, ==, test_strs[i++]);
2999     g_assert (i == 3);
3000
3001     g_variant_iter_free (array);
3002
3003     /* start over */
3004     g_variant_iter_init (&tuple, value);
3005     g_variant_iter_next (&tuple, "as", &array);
3006
3007     i = 0;
3008     while (g_variant_iter_loop (array, "&s", &str))
3009       g_assert_cmpstr (str, ==, test_strs[i++]);
3010     g_assert (i == 3);
3011
3012     g_variant_iter_free (array);
3013
3014     g_variant_iter_next (&tuple, "^a&s", &strv);
3015     g_variant_iter_next (&tuple, "^as", &my_strv);
3016
3017     g_assert_cmpstr (strv[0], ==, "/hello");
3018     g_assert_cmpstr (strv[1], ==, "/world");
3019     g_assert (strv[2] == NULL);
3020     g_assert_cmpstr (my_strv[0], ==, "/hello");
3021     g_assert_cmpstr (my_strv[1], ==, "/world");
3022     g_assert (my_strv[2] == NULL);
3023
3024     g_variant_unref (value);
3025     g_strfreev (my_strv);
3026     g_free (strv);
3027   }
3028
3029   {
3030     const gchar *strvector[] = {"/hello", "/world", NULL};
3031     const gchar *test_strs[] = {"/foo", "/bar", "/baz" };
3032     GVariantBuilder builder;
3033     GVariantIter *array;
3034     GVariantIter tuple;
3035     const gchar **strv;
3036     gchar **my_strv;
3037     GVariant *value;
3038     gchar *str;
3039     gint i;
3040
3041     g_variant_builder_init (&builder, G_VARIANT_TYPE_OBJECT_PATH_ARRAY);
3042     g_variant_builder_add (&builder, "o", "/foo");
3043     g_variant_builder_add (&builder, "o", "/bar");
3044     g_variant_builder_add (&builder, "o", "/baz");
3045     value = g_variant_new("(ao^ao^a&o)", &builder, strvector, strvector);
3046     g_variant_iter_init (&tuple, value);
3047     g_variant_iter_next (&tuple, "ao", &array);
3048
3049     i = 0;
3050     while (g_variant_iter_loop (array, "o", &str))
3051       g_assert_cmpstr (str, ==, test_strs[i++]);
3052     g_assert (i == 3);
3053
3054     g_variant_iter_free (array);
3055
3056     /* start over */
3057     g_variant_iter_init (&tuple, value);
3058     g_variant_iter_next (&tuple, "ao", &array);
3059
3060     i = 0;
3061     while (g_variant_iter_loop (array, "&o", &str))
3062       g_assert_cmpstr (str, ==, test_strs[i++]);
3063     g_assert (i == 3);
3064
3065     g_variant_iter_free (array);
3066
3067     g_variant_iter_next (&tuple, "^a&o", &strv);
3068     g_variant_iter_next (&tuple, "^ao", &my_strv);
3069
3070     g_assert_cmpstr (strv[0], ==, "/hello");
3071     g_assert_cmpstr (strv[1], ==, "/world");
3072     g_assert (strv[2] == NULL);
3073     g_assert_cmpstr (my_strv[0], ==, "/hello");
3074     g_assert_cmpstr (my_strv[1], ==, "/world");
3075     g_assert (my_strv[2] == NULL);
3076
3077     g_variant_unref (value);
3078     g_strfreev (my_strv);
3079     g_free (strv);
3080   }
3081
3082   {
3083     const gchar *strvector[] = { "i", "ii", "iii", "iv", "v", "vi", NULL };
3084     GVariantBuilder builder;
3085     GVariantIter iter;
3086     GVariantIter *i2;
3087     GVariantIter *i3;
3088     GVariant *value;
3089     GVariant *sub;
3090     gchar **strv;
3091     gint i;
3092
3093     g_variant_builder_init (&builder, G_VARIANT_TYPE ("aas"));
3094     g_variant_builder_open (&builder, G_VARIANT_TYPE ("as"));
3095     for (i = 0; i < 6; i++)
3096       if (i & 1)
3097         g_variant_builder_add (&builder, "s", strvector[i]);
3098       else
3099         g_variant_builder_add (&builder, "&s", strvector[i]);
3100     g_variant_builder_close (&builder);
3101     g_variant_builder_add (&builder, "^as", strvector);
3102     g_variant_builder_add (&builder, "^as", strvector);
3103     value = g_variant_new ("aas", &builder);
3104
3105     g_variant_iter_init (&iter, value);
3106     while (g_variant_iter_loop (&iter, "^as", &strv))
3107       for (i = 0; i < 6; i++)
3108         g_assert_cmpstr (strv[i], ==, strvector[i]);
3109
3110     g_variant_iter_init (&iter, value);
3111     while (g_variant_iter_loop (&iter, "^a&s", &strv))
3112       for (i = 0; i < 6; i++)
3113         g_assert_cmpstr (strv[i], ==, strvector[i]);
3114
3115     g_variant_iter_init (&iter, value);
3116     while (g_variant_iter_loop (&iter, "as", &i2))
3117       {
3118         gchar *str;
3119
3120         i = 0;
3121         while (g_variant_iter_loop (i2, "s", &str))
3122           g_assert_cmpstr (str, ==, strvector[i++]);
3123         g_assert (i == 6);
3124       }
3125
3126     g_variant_iter_init (&iter, value);
3127     i3 = g_variant_iter_copy (&iter);
3128     while (g_variant_iter_loop (&iter, "@as", &sub))
3129       {
3130         gchar *str = g_variant_print (sub, TRUE);
3131         g_assert_cmpstr (str, ==,
3132                          "['i', 'ii', 'iii', 'iv', 'v', 'vi']");
3133         g_free (str);
3134       }
3135
3136   if (do_failed_test ("*NULL has already been returned*"))
3137     {
3138       g_variant_iter_next_value (&iter);
3139       abort ();
3140     }
3141
3142
3143     while (g_variant_iter_loop (i3, "*", &sub))
3144       {
3145         gchar *str = g_variant_print (sub, TRUE);
3146         g_assert_cmpstr (str, ==,
3147                          "['i', 'ii', 'iii', 'iv', 'v', 'vi']");
3148         g_free (str);
3149       }
3150
3151     g_variant_iter_free (i3);
3152
3153     for (i = 0; i < g_variant_n_children (value); i++)
3154       {
3155         gint j;
3156
3157         g_variant_get_child (value, i, "*", &sub);
3158
3159         for (j = 0; j < g_variant_n_children (sub); j++)
3160           {
3161             const gchar *str = NULL;
3162             GVariant *cval;
3163
3164             g_variant_get_child (sub, j, "&s", &str);
3165             g_assert_cmpstr (str, ==, strvector[j]);
3166
3167             cval = g_variant_get_child_value (sub, j);
3168             g_variant_get (cval, "&s", &str);
3169             g_assert_cmpstr (str, ==, strvector[j]);
3170             g_variant_unref (cval);
3171           }
3172
3173         g_variant_unref (sub);
3174       }
3175
3176     g_variant_unref (value);
3177   }
3178
3179   {
3180     gboolean justs[10];
3181     GVariant *value;
3182
3183     GVariant *vval;
3184     guchar byteval;
3185     gboolean bval;
3186     gint16 i16val;
3187     guint16 u16val;
3188     gint32 i32val;
3189     guint32 u32val;
3190     gint64 i64val;
3191     guint64 u64val;
3192     gdouble dval;
3193     gint32 hval;
3194
3195     /* test all 'nothing' */
3196     value = g_variant_new ("(mymbmnmqmimumxmtmhmdmv)",
3197                            FALSE, 'a',
3198                            FALSE, TRUE,
3199                            FALSE, (gint16) 123,
3200                            FALSE, (guint16) 123,
3201                            FALSE, (gint32) 123,
3202                            FALSE, (guint32) 123,
3203                            FALSE, (gint64) 123,
3204                            FALSE, (guint64) 123,
3205                            FALSE, (gint32) -1,
3206                            FALSE, (gdouble) 37.5,
3207                            NULL);
3208
3209     /* both NULL */
3210     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3211                    NULL, NULL,
3212                    NULL, NULL,
3213                    NULL, NULL,
3214                    NULL, NULL,
3215                    NULL, NULL,
3216                    NULL, NULL,
3217                    NULL, NULL,
3218                    NULL, NULL,
3219                    NULL, NULL,
3220                    NULL, NULL,
3221                    NULL);
3222
3223     /* NULL values */
3224     memset (justs, 1, sizeof justs);
3225     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3226                    &justs[0], NULL,
3227                    &justs[1], NULL,
3228                    &justs[2], NULL,
3229                    &justs[3], NULL,
3230                    &justs[4], NULL,
3231                    &justs[5], NULL,
3232                    &justs[6], NULL,
3233                    &justs[7], NULL,
3234                    &justs[8], NULL,
3235                    &justs[9], NULL,
3236                    NULL);
3237     g_assert (!(justs[0] || justs[1] || justs[2] || justs[3] || justs[4] ||
3238                 justs[5] || justs[6] || justs[7] || justs[8] || justs[9]));
3239
3240     /* both non-NULL */
3241     memset (justs, 1, sizeof justs);
3242     byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3243     vval = (void *) 1;
3244     bval = TRUE;
3245     dval = 88.88;
3246     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3247                    &justs[0], &byteval,
3248                    &justs[1], &bval,
3249                    &justs[2], &i16val,
3250                    &justs[3], &u16val,
3251                    &justs[4], &i32val,
3252                    &justs[5], &u32val,
3253                    &justs[6], &i64val,
3254                    &justs[7], &u64val,
3255                    &justs[8], &hval,
3256                    &justs[9], &dval,
3257                    &vval);
3258     g_assert (!(justs[0] || justs[1] || justs[2] || justs[3] || justs[4] ||
3259                 justs[5] || justs[6] || justs[7] || justs[8] || justs[9]));
3260     g_assert (byteval == '\0' && bval == FALSE);
3261     g_assert (i16val == 0 && u16val == 0 && i32val == 0 &&
3262               u32val == 0 && i64val == 0 && u64val == 0 &&
3263               hval == 0 && dval == 0.0);
3264     g_assert (vval == NULL);
3265
3266     /* NULL justs */
3267     byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3268     vval = (void *) 1;
3269     bval = TRUE;
3270     dval = 88.88;
3271     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3272                    NULL, &byteval,
3273                    NULL, &bval,
3274                    NULL, &i16val,
3275                    NULL, &u16val,
3276                    NULL, &i32val,
3277                    NULL, &u32val,
3278                    NULL, &i64val,
3279                    NULL, &u64val,
3280                    NULL, &hval,
3281                    NULL, &dval,
3282                    &vval);
3283     g_assert (byteval == '\0' && bval == FALSE);
3284     g_assert (i16val == 0 && u16val == 0 && i32val == 0 &&
3285               u32val == 0 && i64val == 0 && u64val == 0 &&
3286               hval == 0 && dval == 0.0);
3287     g_assert (vval == NULL);
3288
3289     g_variant_unref (value);
3290
3291
3292     /* test all 'just' */
3293     value = g_variant_new ("(mymbmnmqmimumxmtmhmdmv)",
3294                            TRUE, 'a',
3295                            TRUE, TRUE,
3296                            TRUE, (gint16) 123,
3297                            TRUE, (guint16) 123,
3298                            TRUE, (gint32) 123,
3299                            TRUE, (guint32) 123,
3300                            TRUE, (gint64) 123,
3301                            TRUE, (guint64) 123,
3302                            TRUE, (gint32) -1,
3303                            TRUE, (gdouble) 37.5,
3304                            g_variant_new ("()"));
3305
3306     /* both NULL */
3307     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3308                    NULL, NULL,
3309                    NULL, NULL,
3310                    NULL, NULL,
3311                    NULL, NULL,
3312                    NULL, NULL,
3313                    NULL, NULL,
3314                    NULL, NULL,
3315                    NULL, NULL,
3316                    NULL, NULL,
3317                    NULL, NULL,
3318                    NULL);
3319
3320     /* NULL values */
3321     memset (justs, 0, sizeof justs);
3322     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3323                    &justs[0], NULL,
3324                    &justs[1], NULL,
3325                    &justs[2], NULL,
3326                    &justs[3], NULL,
3327                    &justs[4], NULL,
3328                    &justs[5], NULL,
3329                    &justs[6], NULL,
3330                    &justs[7], NULL,
3331                    &justs[8], NULL,
3332                    &justs[9], NULL,
3333                    NULL);
3334     g_assert (justs[0] && justs[1] && justs[2] && justs[3] && justs[4] &&
3335               justs[5] && justs[6] && justs[7] && justs[8] && justs[9]);
3336
3337     /* both non-NULL */
3338     memset (justs, 0, sizeof justs);
3339     byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3340     vval = (void *) 1;
3341     bval = FALSE;
3342     dval = 88.88;
3343     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3344                    &justs[0], &byteval,
3345                    &justs[1], &bval,
3346                    &justs[2], &i16val,
3347                    &justs[3], &u16val,
3348                    &justs[4], &i32val,
3349                    &justs[5], &u32val,
3350                    &justs[6], &i64val,
3351                    &justs[7], &u64val,
3352                    &justs[8], &hval,
3353                    &justs[9], &dval,
3354                    &vval);
3355     g_assert (justs[0] && justs[1] && justs[2] && justs[3] && justs[4] &&
3356               justs[5] && justs[6] && justs[7] && justs[8] && justs[9]);
3357     g_assert (byteval == 'a' && bval == TRUE);
3358     g_assert (i16val == 123 && u16val == 123 && i32val == 123 &&
3359               u32val == 123 && i64val == 123 && u64val == 123 &&
3360               hval == -1 && dval == 37.5);
3361     g_assert (g_variant_is_of_type (vval, G_VARIANT_TYPE_UNIT));
3362     g_variant_unref (vval);
3363
3364     /* NULL justs */
3365     byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3366     vval = (void *) 1;
3367     bval = TRUE;
3368     dval = 88.88;
3369     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3370                    NULL, &byteval,
3371                    NULL, &bval,
3372                    NULL, &i16val,
3373                    NULL, &u16val,
3374                    NULL, &i32val,
3375                    NULL, &u32val,
3376                    NULL, &i64val,
3377                    NULL, &u64val,
3378                    NULL, &hval,
3379                    NULL, &dval,
3380                    &vval);
3381     g_assert (byteval == 'a' && bval == TRUE);
3382     g_assert (i16val == 123 && u16val == 123 && i32val == 123 &&
3383               u32val == 123 && i64val == 123 && u64val == 123 &&
3384               hval == -1 && dval == 37.5);
3385     g_assert (g_variant_is_of_type (vval, G_VARIANT_TYPE_UNIT));
3386     g_variant_unref (vval);
3387
3388     g_variant_unref (value);
3389   }
3390
3391   {
3392     GVariant *value;
3393     gchar *str;
3394
3395     value = g_variant_new ("(masas)", NULL, NULL);
3396     g_variant_ref_sink (value);
3397
3398     str = g_variant_print (value, TRUE);
3399     g_assert_cmpstr (str, ==, "(@mas nothing, @as [])");
3400     g_variant_unref (value);
3401     g_free (str);
3402
3403     if (do_failed_test ("*which type of empty array*"))
3404       g_variant_new ("(a{s*})", NULL);
3405   }
3406
3407   g_variant_type_info_assert_no_infos ();
3408 }
3409
3410 static void
3411 hash_get (GVariant    *value,
3412           const gchar *format,
3413           ...)
3414 {
3415   const gchar *endptr = NULL;
3416   gboolean hash;
3417   va_list ap;
3418
3419   hash = g_str_has_suffix (format, "#");
3420
3421   va_start (ap, format);
3422   g_variant_get_va (value, format, hash ? &endptr : NULL, &ap);
3423   va_end (ap);
3424
3425   if (hash)
3426     g_assert (*endptr == '#');
3427 }
3428
3429 static GVariant *
3430 hash_new (const gchar *format,
3431           ...)
3432 {
3433   const gchar *endptr = NULL;
3434   GVariant *value;
3435   gboolean hash;
3436   va_list ap;
3437
3438   hash = g_str_has_suffix (format, "#");
3439
3440   va_start (ap, format);
3441   value = g_variant_new_va (format, hash ? &endptr : NULL, &ap);
3442   va_end (ap);
3443
3444   if (hash)
3445     g_assert (*endptr == '#');
3446
3447   return value;
3448 }
3449
3450 static void
3451 test_valist (void)
3452 {
3453   GVariant *value;
3454   gint32 x;
3455
3456   x = 0;
3457   value = hash_new ("i", 234);
3458   hash_get (value, "i", &x);
3459   g_assert (x == 234);
3460   g_variant_unref (value);
3461
3462   x = 0;
3463   value = hash_new ("i#", 234);
3464   hash_get (value, "i#", &x);
3465   g_assert (x == 234);
3466   g_variant_unref (value);
3467
3468   g_variant_type_info_assert_no_infos ();
3469 }
3470
3471 static void
3472 test_builder_memory (void)
3473 {
3474   GVariantBuilder *hb;
3475   GVariantBuilder sb;
3476
3477   hb = g_variant_builder_new  (G_VARIANT_TYPE_ARRAY);
3478   g_variant_builder_open (hb, G_VARIANT_TYPE_ARRAY);
3479   g_variant_builder_open (hb, G_VARIANT_TYPE_ARRAY);
3480   g_variant_builder_open (hb, G_VARIANT_TYPE_ARRAY);
3481   g_variant_builder_add (hb, "s", "some value");
3482   g_variant_builder_ref (hb);
3483   g_variant_builder_unref (hb);
3484   g_variant_builder_unref (hb);
3485
3486   hb = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
3487   g_variant_builder_unref (hb);
3488
3489   hb = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
3490   g_variant_builder_clear (hb);
3491   g_variant_builder_unref (hb);
3492
3493   g_variant_builder_init (&sb, G_VARIANT_TYPE_ARRAY);
3494   g_variant_builder_open (&sb, G_VARIANT_TYPE_ARRAY);
3495   g_variant_builder_open (&sb, G_VARIANT_TYPE_ARRAY);
3496   g_variant_builder_add (&sb, "s", "some value");
3497   g_variant_builder_clear (&sb);
3498
3499   g_variant_type_info_assert_no_infos ();
3500 }
3501
3502 static void
3503 test_hashing (void)
3504 {
3505   GVariant *items[4096];
3506   GHashTable *table;
3507   gint i;
3508
3509   table = g_hash_table_new_full (g_variant_hash, g_variant_equal,
3510                                  (GDestroyNotify ) g_variant_unref,
3511                                  NULL);
3512
3513   for (i = 0; i < G_N_ELEMENTS (items); i++)
3514     {
3515       TreeInstance *tree;
3516       gint j;
3517
3518  again:
3519       tree = tree_instance_new (NULL, 0);
3520       items[i] = tree_instance_get_gvariant (tree);
3521       tree_instance_free (tree);
3522
3523       for (j = 0; j < i; j++)
3524         if (g_variant_equal (items[i], items[j]))
3525           {
3526             g_variant_unref (items[i]);
3527             goto again;
3528           }
3529
3530       g_hash_table_insert (table,
3531                            g_variant_ref_sink (items[i]),
3532                            GINT_TO_POINTER (i));
3533     }
3534
3535   for (i = 0; i < G_N_ELEMENTS (items); i++)
3536     {
3537       gpointer result;
3538
3539       result = g_hash_table_lookup (table, items[i]);
3540       g_assert_cmpint (GPOINTER_TO_INT (result), ==, i);
3541     }
3542
3543   g_hash_table_unref (table);
3544
3545   g_variant_type_info_assert_no_infos ();
3546 }
3547
3548 static void
3549 test_gv_byteswap ()
3550 {
3551 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
3552 # define native16(x)  x, 0
3553 # define swapped16(x) 0, x
3554 #else
3555 # define native16(x)  0, x
3556 # define swapped16(x) x, 0
3557 #endif
3558   /* all kinds of of crazy randomised testing already performed on the
3559    * byteswapper in the /gvariant/serialiser/byteswap test and all kinds
3560    * of crazy randomised testing performed against the serialiser
3561    * normalisation functions in the /gvariant/serialiser/fuzz/ tests.
3562    *
3563    * just test a few simple cases here to make sure they each work
3564    */
3565   guchar validbytes[] = { 'a', '\0', swapped16(66), 2,
3566                           0,
3567                           'b', '\0', swapped16(77), 2,
3568                           5, 11 };
3569   guchar corruptbytes[] = { 'a', '\0', swapped16(66), 2,
3570                             0,
3571                             'b', '\0', swapped16(77), 2,
3572                             6, 11 };
3573   guint valid_data[4], corrupt_data[4];
3574   GVariant *value, *swapped;
3575   gchar *string, *string2;
3576
3577   memcpy (valid_data, validbytes, sizeof validbytes);
3578   memcpy (corrupt_data, corruptbytes, sizeof corruptbytes);
3579
3580   /* trusted */
3581   value = g_variant_new_from_data (G_VARIANT_TYPE ("a(sn)"),
3582                                    valid_data, sizeof validbytes, TRUE,
3583                                    NULL, NULL);
3584   swapped = g_variant_byteswap (value);
3585   g_variant_unref (value);
3586   g_assert (g_variant_get_size (swapped) == 13);
3587   string = g_variant_print (swapped, FALSE);
3588   g_variant_unref (swapped);
3589   g_assert_cmpstr (string, ==, "[('a', 66), ('b', 77)]");
3590   g_free (string);
3591
3592   /* untrusted but valid */
3593   value = g_variant_new_from_data (G_VARIANT_TYPE ("a(sn)"),
3594                                    valid_data, sizeof validbytes, FALSE,
3595                                    NULL, NULL);
3596   swapped = g_variant_byteswap (value);
3597   g_variant_unref (value);
3598   g_assert (g_variant_get_size (swapped) == 13);
3599   string = g_variant_print (swapped, FALSE);
3600   g_variant_unref (swapped);
3601   g_assert_cmpstr (string, ==, "[('a', 66), ('b', 77)]");
3602   g_free (string);
3603
3604   /* untrusted, invalid */
3605   value = g_variant_new_from_data (G_VARIANT_TYPE ("a(sn)"),
3606                                    corrupt_data, sizeof corruptbytes, FALSE,
3607                                    NULL, NULL);
3608   string = g_variant_print (value, FALSE);
3609   swapped = g_variant_byteswap (value);
3610   g_variant_unref (value);
3611   g_assert (g_variant_get_size (swapped) == 13);
3612   value = g_variant_byteswap (swapped);
3613   g_variant_unref (swapped);
3614   string2 = g_variant_print (value, FALSE);
3615   g_assert (g_variant_get_size (value) == 13);
3616   g_variant_unref (value);
3617   g_assert_cmpstr (string, ==, string2);
3618   g_free (string2);
3619   g_free (string);
3620 }
3621
3622 static void
3623 test_parser (void)
3624 {
3625   TreeInstance *tree;
3626   GVariant *parsed;
3627   GVariant *value;
3628   gchar *pt, *p;
3629   gchar *res;
3630
3631   tree = tree_instance_new (NULL, 3);
3632   value = tree_instance_get_gvariant (tree);
3633   tree_instance_free (tree);
3634
3635   pt = g_variant_print (value, TRUE);
3636   p = g_variant_print (value, FALSE);
3637
3638   parsed = g_variant_parse (NULL, pt, NULL, NULL, NULL);
3639   res = g_variant_print (parsed, FALSE);
3640   g_assert_cmpstr (p, ==, res);
3641   g_variant_unref (parsed);
3642   g_free (res);
3643
3644   parsed = g_variant_parse (g_variant_get_type (value), p,
3645                             NULL, NULL, NULL);
3646   res = g_variant_print (parsed, TRUE);
3647   g_assert_cmpstr (pt, ==, res);
3648   g_variant_unref (parsed);
3649   g_free (res);
3650
3651   g_variant_unref (value);
3652   g_free (pt);
3653   g_free (p);
3654 }
3655
3656 static void
3657 test_parses (void)
3658 {
3659   gint i;
3660
3661   for (i = 0; i < 100; i++)
3662     {
3663       test_parser ();
3664     }
3665
3666   /* mini test */
3667   {
3668     GError *error = NULL;
3669     gchar str[128];
3670     GVariant *val;
3671     gchar *p, *p2;
3672
3673     for (i = 0; i < 127; i++)
3674       str[i] = i + 1;
3675     str[i] = 0;
3676
3677     val = g_variant_new_string (str);
3678     p = g_variant_print (val, FALSE);
3679     g_variant_unref (val);
3680
3681     val = g_variant_parse (NULL, p, NULL, NULL, &error);
3682     p2 = g_variant_print (val, FALSE);
3683
3684     g_assert_cmpstr (str, ==, g_variant_get_string (val, NULL));
3685     g_assert_cmpstr (p, ==, p2);
3686
3687     g_variant_unref (val);
3688     g_free (p2);
3689     g_free (p);
3690   }
3691
3692   /* another mini test */
3693   {
3694     const gchar *end;
3695     GVariant *value;
3696
3697     value = g_variant_parse (G_VARIANT_TYPE_INT32, "1 2 3", NULL, &end, NULL);
3698     g_assert_cmpint (g_variant_get_int32 (value), ==, 1);
3699     /* make sure endptr returning works */
3700     g_assert_cmpstr (end, ==, " 2 3");
3701     g_variant_unref (value);
3702   }
3703
3704   /* unicode mini test */
3705   {
3706     /* ał𝄞 */
3707     const gchar orig[] = "a\xc5\x82\xf0\x9d\x84\x9e \t\n";
3708     GVariant *value;
3709     gchar *printed;
3710
3711     value = g_variant_new_string (orig);
3712     printed = g_variant_print (value, FALSE);
3713     g_variant_unref (value);
3714
3715     g_assert_cmpstr (printed, ==, "'a\xc5\x82\xf0\x9d\x84\x9e \\t\\n'");
3716     value = g_variant_parse (NULL, printed, NULL, NULL, NULL);
3717     g_assert_cmpstr (g_variant_get_string (value, NULL), ==, orig);
3718     g_variant_unref (value);
3719     g_free (printed);
3720   }
3721
3722   /* inf/nan mini test */
3723   {
3724     const gchar *tests[] = { "inf", "-inf", "nan" };
3725     GVariant *value;
3726     gchar *printed;
3727     gint i;
3728
3729     for (i = 0; i < G_N_ELEMENTS (tests); i++)
3730       {
3731         GError *error = NULL;
3732         value = g_variant_parse (NULL, tests[i], NULL, NULL, &error);
3733         printed = g_variant_print (value, FALSE);
3734         g_assert (g_str_has_prefix (printed, tests[i]));
3735         g_free (printed);
3736         g_variant_unref (value);
3737       }
3738   }
3739
3740   g_variant_type_info_assert_no_infos ();
3741 }
3742
3743 static void
3744 test_parse_failures (void)
3745 {
3746   const gchar *test[] = {
3747     "[1, 2,",                   "6:",              "expected value",
3748     "",                         "0:",              "expected value",
3749     "(1, 2,",                   "6:",              "expected value",
3750     "<1",                       "2:",              "expected `>'",
3751     "[]",                       "0-2:",            "unable to infer",
3752     "(,",                       "1:",              "expected value",
3753     "[4,'']",                   "1-2,3-5:",        "common type",
3754     "[4, '', 5]",               "1-2,4-6:",        "common type",
3755     "['', 4, 5]",               "1-3,5-6:",        "common type",
3756     "[4, 5, '']",               "1-2,7-9:",        "common type",
3757     "[[4], [], ['']]",          "1-4,10-14:",      "common type",
3758     "[[], [4], ['']]",          "5-8,10-14:",      "common type",
3759     "just",                     "4:",              "expected value",
3760     "nothing",                  "0-7:",            "unable to infer",
3761     "just [4, '']",             "6-7,9-11:",       "common type",
3762     "[[4,'']]",                 "2-3,4-6:",        "common type",
3763     "([4,''],)",                "2-3,4-6:",        "common type",
3764     "(4)",                      "2:",              "`,'",
3765     "{}",                       "0-2:",            "unable to infer",
3766     "{[1,2],[3,4]}",            "0-13:",           "basic types",
3767     "{[1,2]:[3,4]}",            "0-13:",           "basic types",
3768     "justt",                    "0-5:",            "unknown keyword",
3769     "nothng",                   "0-6:",            "unknown keyword",
3770     "uint33",                   "0-6:",            "unknown keyword",
3771     "@mi just ''",              "9-11:",           "can not parse as",
3772     "@ai ['']",                 "5-7:",            "can not parse as",
3773     "@(i) ('',)",               "6-8:",            "can not parse as",
3774     "[[], 5]",                  "1-3,5-6:",        "common type",
3775     "[[5], 5]",                 "1-4,6-7:",        "common type",
3776     "5 5",                      "2:",              "expected end of input",
3777     "[5, [5, '']]",             "5-6,8-10:",       "common type",
3778     "@i just 5",                "3-9:",            "can not parse as",
3779     "@i nothing",               "3-10:",           "can not parse as",
3780     "@i []",                    "3-5:",            "can not parse as",
3781     "@i ()",                    "3-5:",            "can not parse as",
3782     "@ai (4,)",                 "4-8:",            "can not parse as",
3783     "@(i) []",                  "5-7:",            "can not parse as",
3784     "(5 5)",                    "3:",              "expected `,'",
3785     "[5 5]",                    "3:",              "expected `,' or `]'",
3786     "(5, 5 5)",                 "6:",              "expected `,' or `)'",
3787     "[5, 5 5]",                 "6:",              "expected `,' or `]'",
3788     "<@i []>",                  "4-6:",            "can not parse as",
3789     "<[5 5]>",                  "4:",              "expected `,' or `]'",
3790     "{[4,''],5}",               "2-3,4-6:",        "common type",
3791     "{5,[4,'']}",               "4-5,6-8:",        "common type",
3792     "@i {1,2}",                 "3-8:",            "can not parse as",
3793     "{@i '', 5}",               "4-6:",            "can not parse as",
3794     "{5, @i ''}",               "7-9:",            "can not parse as",
3795     "@ai {}",                   "4-6:",            "can not parse as",
3796     "{@i '': 5}",               "4-6:",            "can not parse as",
3797     "{5: @i ''}",               "7-9:",            "can not parse as",
3798     "{<4,5}",                   "3:",              "expected `>'",
3799     "{4,<5}",                   "5:",              "expected `>'",
3800     "{4,5,6}",                  "4:",              "expected `}'",
3801     "{5 5}",                    "3:",              "expected `:' or `,'",
3802     "{4: 5: 6}",                "5:",              "expected `,' or `}'",
3803     "{4:5,<6:7}",               "7:",              "expected `>'",
3804     "{4:5,6:<7}",               "9:",              "expected `>'",
3805     "{4:5,6 7}",                "7:",              "expected `:'",
3806     "@o 'foo'",                 "3-8:",            "object path",
3807     "@g 'zzz'",                 "3-8:",            "signature",
3808     "@i true",                  "3-7:",            "can not parse as",
3809     "@z 4",                     "0-2:",            "invalid type",
3810     "@a* []",                   "0-3:",            "definite",
3811     "@ai [3 3]",                "7:",              "expected `,' or `]'",
3812     "18446744073709551616",     "0-20:",           "too big for any type",
3813     "-18446744073709551616",    "0-21:",           "too big for any type",
3814     "byte 256",                 "5-8:",            "out of range for type",
3815     "byte -1",                  "5-7:",            "out of range for type",
3816     "int16 32768",              "6-11:",           "out of range for type",
3817     "int16 -32769",             "6-12:",           "out of range for type",
3818     "uint16 -1",                "7-9:",            "out of range for type",
3819     "uint16 65536",             "7-12:",           "out of range for type",
3820     "2147483648",               "0-10:",           "out of range for type",
3821     "-2147483649",              "0-11:",           "out of range for type",
3822     "uint32 -1",                "7-9:",            "out of range for type",
3823     "uint32 4294967296",        "7-17:",           "out of range for type",
3824     "@x 9223372036854775808",   "3-22:",           "out of range for type",
3825     "@x -9223372036854775809",  "3-23:",           "out of range for type",
3826     "@t -1",                    "3-5:",            "out of range for type",
3827     "@t 18446744073709551616",  "3-23:",           "too big for any type",
3828     "handle 2147483648",        "7-17:",           "out of range for type",
3829     "handle -2147483649",       "7-18:",           "out of range for type",
3830     "1.798e308",                "0-9:",            "too big for any type",
3831     "37.5a488",                 "4-5:",            "invalid character",
3832     "0x7ffgf",                  "5-6:",            "invalid character",
3833     "07758",                    "4-5:",            "invalid character",
3834     "123a5",                    "3-4:",            "invalid character",
3835     "@ai 123",                  "4-7:",            "can not parse as",
3836     "'\"\\'",                   "0-4:",            "unterminated string",
3837     "'\"\\'\\",                 "0-5:",            "unterminated string",
3838     "boolean 4",                "8-9:",            "can not parse as",
3839     "int32 true",               "6-10:",           "can not parse as",
3840     "[double 5, int32 5]",      "1-9,11-18:",      "common type",
3841     "string 4",                 "7-8:",            "can not parse as"
3842   };
3843   gint i;
3844
3845   for (i = 0; i < G_N_ELEMENTS (test); i += 3)
3846     {
3847       GError *error = NULL;
3848       GVariant *value;
3849
3850       value = g_variant_parse (NULL, test[i], NULL, NULL, &error);
3851       g_assert (value == NULL);
3852
3853       if (!strstr (error->message, test[i+2]))
3854         g_error ("test %d: Can't find `%s' in `%s'", i / 3,
3855                  test[i+2], error->message);
3856
3857       if (!g_str_has_prefix (error->message, test[i+1]))
3858         g_error ("test %d: Expected location `%s' in `%s'", i / 3,
3859                  test[i+1], error->message);
3860
3861       g_error_free (error);
3862     }
3863 }
3864
3865 static void
3866 test_parse_positional (void)
3867 {
3868   GVariant *value;
3869   check_and_free (g_variant_new_parsed ("[('one', 1), (%s, 2),"
3870                                         " ('three', %i)]", "two", 3),
3871                   "[('one', 1), ('two', 2), ('three', 3)]");
3872   value = g_variant_new_parsed ("[('one', 1), (%s, 2),"
3873                                 " ('three', %u)]", "two", 3);
3874   g_assert (g_variant_is_of_type (value, G_VARIANT_TYPE ("a(su)")));
3875   check_and_free (value, "[('one', 1), ('two', 2), ('three', 3)]");
3876   check_and_free (g_variant_new_parsed ("{%s:%i}", "one", 1), "{'one': 1}");
3877
3878   if (g_test_undefined ())
3879     {
3880       if (do_failed_test ("*GVariant format string*"))
3881         {
3882           g_variant_new_parsed ("%z");
3883           abort ();
3884         }
3885
3886       if (do_failed_test ("*can not parse as*"))
3887         {
3888           g_variant_new_parsed ("uint32 %i", 2);
3889           abort ();
3890         }
3891
3892       if (do_failed_test ("*expected GVariant of type `i'*"))
3893         {
3894           g_variant_new_parsed ("%@i", g_variant_new_uint32 (2));
3895           abort ();
3896         }
3897     }
3898 }
3899
3900 static void
3901 test_floating (void)
3902 {
3903   GVariant *value;
3904
3905   value = g_variant_new_int32 (42);
3906   g_assert (g_variant_is_floating (value));
3907   g_variant_ref_sink (value);
3908   g_assert (!g_variant_is_floating (value));
3909   g_variant_unref (value);
3910 }
3911
3912 static void
3913 test_bytestring (void)
3914 {
3915   const gchar *test_string = "foo,bar,baz,quux,\xffoooo";
3916   GVariant *value;
3917   gchar **strv;
3918   gchar *str;
3919   const gchar *const_str;
3920   GVariant *untrusted_empty;
3921
3922   strv = g_strsplit (test_string, ",", 0);
3923
3924   value = g_variant_new_bytestring_array ((const gchar **) strv, -1);
3925   g_assert (g_variant_is_floating (value));
3926   g_strfreev (strv);
3927
3928   str = g_variant_print (value, FALSE);
3929   g_variant_unref (value);
3930
3931   value = g_variant_parse (NULL, str, NULL, NULL, NULL);
3932   g_free (str);
3933
3934   strv = g_variant_dup_bytestring_array (value, NULL);
3935   g_variant_unref (value);
3936
3937   str = g_strjoinv (",", strv);
3938   g_strfreev (strv);
3939
3940   g_assert_cmpstr (str, ==, test_string);
3941   g_free (str);
3942
3943   strv = g_strsplit (test_string, ",", 0);
3944   value = g_variant_new ("(^aay^a&ay^ay^&ay)",
3945                          strv, strv, strv[0], strv[0]);
3946   g_strfreev (strv);
3947
3948   g_variant_get_child (value, 0, "^a&ay", &strv);
3949   str = g_strjoinv (",", strv);
3950   g_free (strv);
3951   g_assert_cmpstr (str, ==, test_string);
3952   g_free (str);
3953
3954   g_variant_get_child (value, 0, "^aay", &strv);
3955   str = g_strjoinv (",", strv);
3956   g_strfreev (strv);
3957   g_assert_cmpstr (str, ==, test_string);
3958   g_free (str);
3959
3960   g_variant_get_child (value, 1, "^a&ay", &strv);
3961   str = g_strjoinv (",", strv);
3962   g_free (strv);
3963   g_assert_cmpstr (str, ==, test_string);
3964   g_free (str);
3965
3966   g_variant_get_child (value, 1, "^aay", &strv);
3967   str = g_strjoinv (",", strv);
3968   g_strfreev (strv);
3969   g_assert_cmpstr (str, ==, test_string);
3970   g_free (str);
3971
3972   g_variant_get_child (value, 2, "^ay", &str);
3973   g_assert_cmpstr (str, ==, "foo");
3974   g_free (str);
3975
3976   g_variant_get_child (value, 2, "^&ay", &str);
3977   g_assert_cmpstr (str, ==, "foo");
3978
3979   g_variant_get_child (value, 3, "^ay", &str);
3980   g_assert_cmpstr (str, ==, "foo");
3981   g_free (str);
3982
3983   g_variant_get_child (value, 3, "^&ay", &str);
3984   g_assert_cmpstr (str, ==, "foo");
3985   g_variant_unref (value);
3986
3987   untrusted_empty = g_variant_new_from_data (G_VARIANT_TYPE ("ay"), NULL, 0, FALSE, NULL, NULL);
3988   value = g_variant_get_normal_form (untrusted_empty);
3989   const_str = g_variant_get_bytestring (value);
3990   (void) const_str;
3991   g_variant_unref (value);
3992   g_variant_unref (untrusted_empty);
3993 }
3994
3995 static void
3996 test_lookup_value (void)
3997 {
3998   struct {
3999     const gchar *dict, *key, *value;
4000   } cases[] = {
4001     { "@a{ss} {'x':  'y'}",   "x",  "'y'" },
4002     { "@a{ss} {'x':  'y'}",   "y"         },
4003     { "@a{os} {'/x': 'y'}",   "/x", "'y'" },
4004     { "@a{os} {'/x': 'y'}",   "/y"        },
4005     { "@a{sv} {'x':  <'y'>}", "x",  "'y'" },
4006     { "@a{sv} {'x':  <5>}",   "x",  "5"   },
4007     { "@a{sv} {'x':  <'y'>}", "y"         }
4008   };
4009   gint i;
4010
4011   for (i = 0; i < G_N_ELEMENTS (cases); i++)
4012     {
4013       GVariant *dictionary;
4014       GVariant *value;
4015       gchar *p;
4016       
4017       dictionary = g_variant_parse (NULL, cases[i].dict, NULL, NULL, NULL);
4018       value = g_variant_lookup_value (dictionary, cases[i].key, NULL);
4019       g_variant_unref (dictionary);
4020
4021       if (value == NULL && cases[i].value == NULL)
4022         continue;
4023
4024       g_assert (value && cases[i].value);
4025       p = g_variant_print (value, FALSE);
4026       g_assert_cmpstr (cases[i].value, ==, p);
4027       g_variant_unref (value);
4028       g_free (p);
4029     }
4030 }
4031
4032 static void
4033 test_lookup (void)
4034 {
4035   const gchar *str;
4036   GVariant *dict;
4037   gboolean ok;
4038   gint num;
4039
4040   dict = g_variant_parse (NULL,
4041                           "{'a': <5>, 'b': <'c'>}",
4042                           NULL, NULL, NULL);
4043
4044   ok = g_variant_lookup (dict, "a", "i", &num);
4045   g_assert (ok);
4046   g_assert_cmpint (num, ==, 5);
4047
4048   ok = g_variant_lookup (dict, "a", "&s", &str);
4049   g_assert (!ok);
4050
4051   ok = g_variant_lookup (dict, "q", "&s", &str);
4052   g_assert (!ok);
4053
4054   ok = g_variant_lookup (dict, "b", "i", &num);
4055   g_assert (!ok);
4056
4057   ok = g_variant_lookup (dict, "b", "&s", &str);
4058   g_assert (ok);
4059   g_assert_cmpstr (str, ==, "c");
4060
4061   ok = g_variant_lookup (dict, "q", "&s", &str);
4062   g_assert (!ok);
4063
4064   g_variant_unref (dict);
4065 }
4066
4067 static void
4068 test_compare (void)
4069 {
4070   GVariant *a;
4071   GVariant *b;
4072
4073   a = g_variant_new_byte (5);
4074   b = g_variant_new_byte (6);
4075   g_assert (g_variant_compare (a, b) < 0);
4076   g_variant_unref (a);
4077   g_variant_unref (b);
4078   a = g_variant_new_string ("abc");
4079   b = g_variant_new_string ("abd");
4080   g_assert (g_variant_compare (a, b) < 0);
4081   g_variant_unref (a);
4082   g_variant_unref (b);
4083   a = g_variant_new_boolean (FALSE);
4084   b = g_variant_new_boolean (TRUE);
4085   g_assert (g_variant_compare (a, b) < 0);
4086   g_variant_unref (a);
4087   g_variant_unref (b);
4088 }
4089
4090 static void
4091 test_fixed_array (void)
4092 {
4093   GVariant *a;
4094   gint32 values[5];
4095   const gint32 *elts;
4096   gsize n_elts;
4097   gint i;
4098
4099   n_elts = 0;
4100   a = g_variant_new_parsed ("[1,2,3,4,5]");
4101   elts = g_variant_get_fixed_array (a, &n_elts, sizeof (gint32));
4102   g_assert (n_elts == 5);
4103   for (i = 0; i < 5; i++)
4104     g_assert_cmpint (elts[i], ==, i + 1);
4105   g_variant_unref (a);
4106
4107   n_elts = 0;
4108   for (i = 0; i < 5; i++)
4109     values[i] = i + 1;
4110   a = g_variant_new_fixed_array (G_VARIANT_TYPE_INT32, values,
4111                                  G_N_ELEMENTS (values), sizeof (values[0]));
4112   g_assert_cmpstr (g_variant_get_type_string (a), ==, "ai");
4113   elts = g_variant_get_fixed_array (a, &n_elts, sizeof (gint32));
4114   g_assert (n_elts == 5);
4115   for (i = 0; i < 5; i++)
4116     g_assert_cmpint (elts[i], ==, i + 1);
4117   g_variant_unref (a);
4118 }
4119
4120 int
4121 main (int argc, char **argv)
4122 {
4123   gint i;
4124
4125   g_test_init (&argc, &argv, NULL);
4126
4127   g_test_add_func ("/gvariant/type", test_gvarianttype);
4128   g_test_add_func ("/gvariant/typeinfo", test_gvarianttypeinfo);
4129   g_test_add_func ("/gvariant/serialiser/maybe", test_maybes);
4130   g_test_add_func ("/gvariant/serialiser/array", test_arrays);
4131   g_test_add_func ("/gvariant/serialiser/tuple", test_tuples);
4132   g_test_add_func ("/gvariant/serialiser/variant", test_variants);
4133   g_test_add_func ("/gvariant/serialiser/strings", test_strings);
4134   g_test_add_func ("/gvariant/serialiser/byteswap", test_byteswaps);
4135
4136   for (i = 1; i <= 20; i += 4)
4137     {
4138       char *testname;
4139
4140       testname = g_strdup_printf ("/gvariant/serialiser/fuzz/%d%%", i);
4141       g_test_add_data_func (testname, GINT_TO_POINTER (i),
4142                             (gpointer) test_fuzzes);
4143       g_free (testname);
4144     }
4145
4146   g_test_add_func ("/gvariant/utf8", test_utf8);
4147   g_test_add_func ("/gvariant/containers", test_containers);
4148   g_test_add_func ("/gvariant/format-strings", test_format_strings);
4149   g_test_add_func ("/gvariant/invalid-varargs", test_invalid_varargs);
4150   g_test_add_func ("/gvariant/varargs", test_varargs);
4151   g_test_add_func ("/gvariant/valist", test_valist);
4152   g_test_add_func ("/gvariant/builder-memory", test_builder_memory);
4153   g_test_add_func ("/gvariant/hashing", test_hashing);
4154   g_test_add_func ("/gvariant/byteswap", test_gv_byteswap);
4155   g_test_add_func ("/gvariant/parser", test_parses);
4156   g_test_add_func ("/gvariant/parse-failures", test_parse_failures);
4157   g_test_add_func ("/gvariant/parse-positional", test_parse_positional);
4158   g_test_add_func ("/gvariant/floating", test_floating);
4159   g_test_add_func ("/gvariant/bytestring", test_bytestring);
4160   g_test_add_func ("/gvariant/lookup-value", test_lookup_value);
4161   g_test_add_func ("/gvariant/lookup", test_lookup);
4162   g_test_add_func ("/gvariant/compare", test_compare);
4163   g_test_add_func ("/gvariant/fixed-array", test_fixed_array);
4164
4165   return g_test_run ();
4166 }