GVariant: support comparing booleans
[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
1825     { is_objpath,   2, "/" },
1826     { is_objpath,   3, "/a" },
1827     { is_string,    3, "//" },
1828     { is_objpath,  11, "/some/path" },
1829     { is_string,   12, "/some/path/" },
1830     { is_nval,     11, "/some\0path" },
1831     { is_string,   11, "/some\\path" },
1832     { is_string,   12, "/some//path" },
1833     { is_string,   12, "/some-/path" },
1834
1835     { is_sig,       2, "i" },
1836     { is_sig,       2, "s" },
1837     { is_sig,       5, "(si)" },
1838     { is_string,    4, "(si" },
1839     { is_string,    2, "*" },
1840     { is_sig,       3, "ai" },
1841     { is_string,    3, "mi" },
1842     { is_string,    2, "r" },
1843     { is_sig,      15, "(yyy{sv}ssiai)" },
1844     { is_string,   16, "(yyy{yv}ssiai))" },
1845     { is_string,   15, "(yyy{vv}ssiai)" },
1846     { is_string,   15, "(yyy{sv)ssiai}" }
1847   };
1848   guint i;
1849
1850   for (i = 0; i < G_N_ELEMENTS (test_cases); i++)
1851     {
1852       guint flags;
1853
1854       flags = g_variant_serialiser_is_string (test_cases[i].data,
1855                                               test_cases[i].size)
1856         ? 1 : 0;
1857
1858       flags |= g_variant_serialiser_is_object_path (test_cases[i].data,
1859                                                     test_cases[i].size)
1860         ? 2 : 0;
1861
1862       flags |= g_variant_serialiser_is_signature (test_cases[i].data,
1863                                                   test_cases[i].size)
1864         ? 4 : 0;
1865
1866       g_assert (flags == test_cases[i].flags);
1867     }
1868 }
1869
1870 typedef struct _TreeInstance TreeInstance;
1871 struct _TreeInstance
1872 {
1873   GVariantTypeInfo *info;
1874
1875   TreeInstance **children;
1876   gsize n_children;
1877
1878   union {
1879     guint64 integer;
1880     gdouble floating;
1881     gchar string[32];
1882   } data;
1883   gsize data_size;
1884 };
1885
1886 static GVariantType *
1887 make_random_definite_type (int depth)
1888 {
1889   GString *description;
1890   GString *type_string;
1891   GVariantType *type;
1892
1893   description = g_string_new (NULL);
1894   type_string = g_string_new (NULL);
1895   type = append_type_string (type_string, description, TRUE, depth);
1896   g_string_free (description, TRUE);
1897   g_string_free (type_string, TRUE);
1898
1899   return type;
1900 }
1901
1902 static void
1903 make_random_string (gchar              *string,
1904                     gsize               size,
1905                     const GVariantType *type)
1906 {
1907   gint i;
1908
1909   /* create strings that are valid signature strings */
1910 #define good_chars "bynqiuxthdsog"
1911
1912   for (i = 0; i < size - 1; i++)
1913     string[i] = good_chars[g_test_rand_int_range (0, strlen (good_chars))];
1914   string[i] = '\0';
1915
1916   /* in case we need an object path, prefix a '/' */
1917   if (*g_variant_type_peek_string (type) == 'o')
1918     string[0] = '/';
1919
1920 #undef good_chars
1921 }
1922
1923 static TreeInstance *
1924 tree_instance_new (const GVariantType *type,
1925                    int                 depth)
1926 {
1927   const GVariantType *child_type = NULL;
1928   GVariantType *mytype = NULL;
1929   TreeInstance *instance;
1930   gboolean is_tuple_type;
1931
1932   if (type == NULL)
1933     type = mytype = make_random_definite_type (depth);
1934
1935   instance = g_slice_new (TreeInstance);
1936   instance->info = g_variant_type_info_get (type);
1937   instance->children = NULL;
1938   instance->n_children = 0;
1939   instance->data_size = 0;
1940
1941   is_tuple_type = FALSE;
1942
1943   switch (*g_variant_type_peek_string (type))
1944     {
1945     case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
1946       instance->n_children = g_test_rand_int_range (0, 2);
1947       child_type = g_variant_type_element (type);
1948       break;
1949
1950     case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
1951       instance->n_children = g_test_rand_int_range (0, MAX_ARRAY_CHILDREN);
1952       child_type = g_variant_type_element (type);
1953       break;
1954
1955     case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
1956     case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
1957       instance->n_children = g_variant_type_n_items (type);
1958       child_type = g_variant_type_first (type);
1959       is_tuple_type = TRUE;
1960       break;
1961
1962     case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
1963       instance->n_children = 1;
1964       child_type = NULL;
1965       break;
1966
1967     case 'b':
1968       instance->data.integer = g_test_rand_int_range (0, 2);
1969       instance->data_size = 1;
1970       break;
1971
1972     case 'y':
1973       instance->data.integer = g_test_rand_int ();
1974       instance->data_size = 1;
1975       break;
1976
1977     case 'n': case 'q':
1978       instance->data.integer = g_test_rand_int ();
1979       instance->data_size = 2;
1980       break;
1981
1982     case 'i': case 'u': case 'h':
1983       instance->data.integer = g_test_rand_int ();
1984       instance->data_size = 4;
1985       break;
1986
1987     case 'x': case 't':
1988       instance->data.integer = g_test_rand_int ();
1989       instance->data.integer <<= 32;
1990       instance->data.integer |= (guint32) g_test_rand_int ();
1991       instance->data_size = 8;
1992       break;
1993
1994     case 'd':
1995       instance->data.floating = g_test_rand_double ();
1996       instance->data_size = 8;
1997       break;
1998
1999     case 's': case 'o': case 'g':
2000       instance->data_size = g_test_rand_int_range (10, 20);
2001       make_random_string (instance->data.string, instance->data_size, type);
2002       break;
2003     }
2004
2005   if (instance->data_size == 0)
2006     /* no data -> it is a container */
2007     {
2008       guint i;
2009
2010       instance->children = g_new (TreeInstance *, instance->n_children);
2011
2012       for (i = 0; i < instance->n_children; i++)
2013         {
2014           instance->children[i] = tree_instance_new (child_type, depth - 1);
2015
2016           if (is_tuple_type)
2017             child_type = g_variant_type_next (child_type);
2018         }
2019
2020       g_assert (!is_tuple_type || child_type == NULL);
2021     }
2022
2023   g_variant_type_free (mytype);
2024
2025   return instance;
2026 }
2027
2028 static void
2029 tree_instance_free (TreeInstance *instance)
2030 {
2031   gint i;
2032
2033   g_variant_type_info_unref (instance->info);
2034   for (i = 0; i < instance->n_children; i++)
2035     tree_instance_free (instance->children[i]);
2036   g_free (instance->children);
2037   g_slice_free (TreeInstance, instance);
2038 }
2039
2040 static gboolean i_am_writing_byteswapped;
2041
2042 static void
2043 tree_filler (GVariantSerialised *serialised,
2044              gpointer            data)
2045 {
2046   TreeInstance *instance = data;
2047
2048   if (serialised->type_info == NULL)
2049     serialised->type_info = instance->info;
2050
2051   if (instance->data_size == 0)
2052     /* is a container */
2053     {
2054       if (serialised->size == 0)
2055         serialised->size =
2056           g_variant_serialiser_needed_size (instance->info, tree_filler,
2057                                             (gpointer *) instance->children,
2058                                             instance->n_children);
2059
2060       if (serialised->data)
2061         g_variant_serialiser_serialise (*serialised, tree_filler,
2062                                         (gpointer *) instance->children,
2063                                         instance->n_children);
2064     }
2065   else
2066     /* it is a leaf */
2067     {
2068       if (serialised->size == 0)
2069         serialised->size = instance->data_size;
2070
2071       if (serialised->data)
2072         {
2073           switch (instance->data_size)
2074             {
2075             case 1:
2076               *serialised->data = instance->data.integer;
2077               break;
2078
2079             case 2:
2080               {
2081                 guint16 value = instance->data.integer;
2082
2083                 if (i_am_writing_byteswapped)
2084                   value = GUINT16_SWAP_LE_BE (value);
2085
2086                 *(guint16 *) serialised->data = value;
2087               }
2088               break;
2089
2090             case 4:
2091               {
2092                 guint32 value = instance->data.integer;
2093
2094                 if (i_am_writing_byteswapped)
2095                   value = GUINT32_SWAP_LE_BE (value);
2096
2097                 *(guint32 *) serialised->data = value;
2098               }
2099               break;
2100
2101             case 8:
2102               {
2103                 guint64 value = instance->data.integer;
2104
2105                 if (i_am_writing_byteswapped)
2106                   value = GUINT64_SWAP_LE_BE (value);
2107
2108                 *(guint64 *) serialised->data = value;
2109               }
2110               break;
2111
2112             default:
2113               memcpy (serialised->data,
2114                       instance->data.string,
2115                       instance->data_size);
2116               break;
2117             }
2118         }
2119     }
2120 }
2121
2122 static gboolean
2123 check_tree (TreeInstance       *instance,
2124             GVariantSerialised  serialised)
2125 {
2126   if (instance->info != serialised.type_info)
2127     return FALSE;
2128
2129   if (instance->data_size == 0)
2130     /* is a container */
2131     {
2132       gint i;
2133
2134       if (g_variant_serialised_n_children (serialised) !=
2135           instance->n_children)
2136         return FALSE;
2137
2138       for (i = 0; i < instance->n_children; i++)
2139         {
2140           GVariantSerialised child;
2141           gpointer data = NULL;
2142           gboolean ok;
2143
2144           child = g_variant_serialised_get_child (serialised, i);
2145           if (child.size && child.data == NULL)
2146             child.data = data = g_malloc0 (child.size);
2147           ok = check_tree (instance->children[i], child);
2148           g_variant_type_info_unref (child.type_info);
2149           g_free (data);
2150
2151           if (!ok)
2152             return FALSE;
2153         }
2154
2155       return TRUE;
2156     }
2157   else
2158     /* it is a leaf */
2159     {
2160       switch (instance->data_size)
2161         {
2162         case 1:
2163           g_assert (serialised.size == 1);
2164           return *(guint8 *) serialised.data ==
2165                   (guint8) instance->data.integer;
2166
2167         case 2:
2168           g_assert (serialised.size == 2);
2169           return *(guint16 *) serialised.data ==
2170                   (guint16) instance->data.integer;
2171
2172         case 4:
2173           g_assert (serialised.size == 4);
2174           return *(guint32 *) serialised.data ==
2175                   (guint32) instance->data.integer;
2176
2177         case 8:
2178           g_assert (serialised.size == 8);
2179           return *(guint64 *) serialised.data ==
2180                   (guint64) instance->data.integer;
2181
2182         default:
2183           if (serialised.size != instance->data_size)
2184             return FALSE;
2185
2186           return memcmp (serialised.data,
2187                          instance->data.string,
2188                          instance->data_size) == 0;
2189         }
2190     }
2191 }
2192
2193 static void
2194 serialise_tree (TreeInstance       *tree,
2195                 GVariantSerialised *serialised)
2196 {
2197   GVariantSerialised empty = {  };
2198
2199   *serialised = empty;
2200   tree_filler (serialised, tree);
2201   serialised->data = g_malloc (serialised->size);
2202   tree_filler (serialised, tree);
2203 }
2204
2205 static void
2206 test_byteswap (void)
2207 {
2208   GVariantSerialised one, two;
2209   TreeInstance *tree;
2210
2211   tree = tree_instance_new (NULL, 3);
2212   serialise_tree (tree, &one);
2213
2214   i_am_writing_byteswapped = TRUE;
2215   serialise_tree (tree, &two);
2216   i_am_writing_byteswapped = FALSE;
2217
2218   g_variant_serialised_byteswap (two);
2219
2220   g_assert_cmpint (one.size, ==, two.size);
2221   g_assert (memcmp (one.data, two.data, one.size) == 0);
2222
2223   tree_instance_free (tree);
2224   g_free (one.data);
2225   g_free (two.data);
2226 }
2227
2228 static void
2229 test_byteswaps (void)
2230 {
2231   int i;
2232
2233   for (i = 0; i < 200; i++)
2234     test_byteswap ();
2235
2236   g_variant_type_info_assert_no_infos ();
2237 }
2238
2239 static void
2240 test_fuzz (gdouble *fuzziness)
2241 {
2242   GVariantSerialised serialised;
2243   TreeInstance *tree;
2244
2245   /* make an instance */
2246   tree = tree_instance_new (NULL, 3);
2247
2248   /* serialise it */
2249   serialise_tree (tree, &serialised);
2250
2251   g_assert (g_variant_serialised_is_normal (serialised));
2252   g_assert (check_tree (tree, serialised));
2253
2254   if (serialised.size)
2255     {
2256       gboolean fuzzed = FALSE;
2257       gboolean a, b;
2258
2259       while (!fuzzed)
2260         {
2261           gint i;
2262
2263           for (i = 0; i < serialised.size; i++)
2264             if (randomly (*fuzziness))
2265               {
2266                 serialised.data[i] += g_test_rand_int_range (1, 256);
2267                 fuzzed = TRUE;
2268               }
2269         }
2270
2271       /* at least one byte in the serialised data has changed.
2272        *
2273        * this means that at least one of the following is true:
2274        *
2275        *    - the serialised data now represents a different value:
2276        *        check_tree() will return FALSE
2277        *
2278        *    - the serialised data is in non-normal form:
2279        *        g_variant_serialiser_is_normal() will return FALSE
2280        *
2281        * we always do both checks to increase exposure of the serialiser
2282        * to corrupt data.
2283        */
2284       a = g_variant_serialised_is_normal (serialised);
2285       b = check_tree (tree, serialised);
2286
2287       g_assert (!a || !b);
2288     }
2289
2290   tree_instance_free (tree);
2291   g_free (serialised.data);
2292 }
2293
2294
2295 static void
2296 test_fuzzes (gpointer data)
2297 {
2298   gdouble fuzziness;
2299   int i;
2300
2301   fuzziness = GPOINTER_TO_INT (data) / 100.;
2302
2303   for (i = 0; i < 200; i++)
2304     test_fuzz (&fuzziness);
2305
2306   g_variant_type_info_assert_no_infos ();
2307 }
2308
2309 static GVariant *
2310 tree_instance_get_gvariant (TreeInstance *tree)
2311 {
2312   const GVariantType *type;
2313   GVariant *result;
2314
2315   type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
2316
2317   switch (g_variant_type_info_get_type_char (tree->info))
2318     {
2319     case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
2320       {
2321         const GVariantType *child_type;
2322         GVariant *child;
2323
2324         if (tree->n_children)
2325           child = tree_instance_get_gvariant (tree->children[0]);
2326         else
2327           child = NULL;
2328
2329         child_type = g_variant_type_element (type);
2330
2331         if (child != NULL && randomly (0.5))
2332           child_type = NULL;
2333
2334         result = g_variant_new_maybe (child_type, child);
2335       }
2336       break;
2337
2338     case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
2339       {
2340         const GVariantType *child_type;
2341         GVariant **children;
2342         gint i;
2343
2344         children = g_new (GVariant *, tree->n_children);
2345         for (i = 0; i < tree->n_children; i++)
2346           children[i] = tree_instance_get_gvariant (tree->children[i]);
2347
2348         child_type = g_variant_type_element (type);
2349
2350         if (i > 0 && randomly (0.5))
2351           child_type = NULL;
2352
2353         result = g_variant_new_array (child_type, children, tree->n_children);
2354         g_free (children);
2355       }
2356       break;
2357
2358     case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
2359       {
2360         GVariant **children;
2361         gint i;
2362
2363         children = g_new (GVariant *, tree->n_children);
2364         for (i = 0; i < tree->n_children; i++)
2365           children[i] = tree_instance_get_gvariant (tree->children[i]);
2366
2367         result = g_variant_new_tuple (children, tree->n_children);
2368         g_free (children);
2369       }
2370       break;
2371
2372     case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
2373       {
2374         GVariant *key, *val;
2375
2376         g_assert (tree->n_children == 2);
2377
2378         key = tree_instance_get_gvariant (tree->children[0]);
2379         val = tree_instance_get_gvariant (tree->children[1]);
2380
2381         result = g_variant_new_dict_entry (key, val);
2382       }
2383       break;
2384
2385     case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
2386       {
2387         GVariant *value;
2388
2389         g_assert (tree->n_children == 1);
2390
2391         value = tree_instance_get_gvariant (tree->children[0]);
2392         result = g_variant_new_variant (value);
2393       }
2394       break;
2395
2396     case 'b':
2397       result = g_variant_new_boolean (tree->data.integer > 0);
2398       break;
2399
2400     case 'y':
2401       result = g_variant_new_byte (tree->data.integer);
2402       break;
2403
2404     case 'n':
2405       result = g_variant_new_int16 (tree->data.integer);
2406       break;
2407
2408     case 'q':
2409       result = g_variant_new_uint16 (tree->data.integer);
2410       break;
2411
2412     case 'i':
2413       result = g_variant_new_int32 (tree->data.integer);
2414       break;
2415
2416     case 'u':
2417       result = g_variant_new_uint32 (tree->data.integer);
2418       break;
2419
2420     case 'x':
2421       result = g_variant_new_int64 (tree->data.integer);
2422       break;
2423
2424     case 't':
2425       result = g_variant_new_uint64 (tree->data.integer);
2426       break;
2427
2428     case 'h':
2429       result = g_variant_new_handle (tree->data.integer);
2430       break;
2431
2432     case 'd':
2433       result = g_variant_new_double (tree->data.floating);
2434       break;
2435
2436     case 's':
2437       result = g_variant_new_string (tree->data.string);
2438       break;
2439
2440     case 'o':
2441       result = g_variant_new_object_path (tree->data.string);
2442       break;
2443
2444     case 'g':
2445       result = g_variant_new_signature (tree->data.string);
2446       break;
2447
2448     default:
2449       g_assert_not_reached ();
2450     }
2451
2452   return result;
2453 }
2454
2455 static gboolean
2456 tree_instance_check_gvariant (TreeInstance *tree,
2457                               GVariant     *value)
2458 {
2459   const GVariantType *type;
2460
2461   type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
2462   g_assert (g_variant_is_of_type (value, type));
2463
2464   switch (g_variant_type_info_get_type_char (tree->info))
2465     {
2466     case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
2467       {
2468         GVariant *child;
2469         gboolean equal;
2470
2471         child = g_variant_get_maybe (value);
2472
2473         if (child != NULL && tree->n_children == 1)
2474           equal = tree_instance_check_gvariant (tree->children[0], child);
2475         else if (child == NULL && tree->n_children == 0)
2476           equal = TRUE;
2477         else
2478           equal = FALSE;
2479
2480         if (child != NULL)
2481           g_variant_unref (child);
2482
2483         return equal;
2484       }
2485       break;
2486
2487     case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
2488     case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
2489     case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
2490       {
2491         gsize i;
2492
2493         if (g_variant_n_children (value) != tree->n_children)
2494           return FALSE;
2495
2496         for (i = 0; i < tree->n_children; i++)
2497           {
2498             GVariant *child;
2499             gboolean equal;
2500
2501             child = g_variant_get_child_value (value, i);
2502             equal = tree_instance_check_gvariant (tree->children[i], child);
2503             g_variant_unref (child);
2504
2505             if (!equal)
2506               return FALSE;
2507           }
2508
2509         return TRUE;
2510       }
2511       break;
2512
2513     case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
2514       {
2515         const gchar *str1, *str2;
2516         GVariant *child;
2517         gboolean equal;
2518
2519         child = g_variant_get_variant (value);
2520         str1 = g_variant_get_type_string (child);
2521         str2 = g_variant_type_info_get_type_string (tree->children[0]->info);
2522         /* GVariant only keeps one copy of type strings around */
2523         equal = str1 == str2 &&
2524                 tree_instance_check_gvariant (tree->children[0], child);
2525
2526         g_variant_unref (child);
2527
2528         return equal;
2529       }
2530       break;
2531
2532     case 'b':
2533       return g_variant_get_boolean (value) == tree->data.integer;
2534
2535     case 'y':
2536       return g_variant_get_byte (value) == (guchar) tree->data.integer;
2537
2538     case 'n':
2539       return g_variant_get_int16 (value) == (gint16) tree->data.integer;
2540
2541     case 'q':
2542       return g_variant_get_uint16 (value) == (guint16) tree->data.integer;
2543
2544     case 'i':
2545       return g_variant_get_int32 (value) == (gint32) tree->data.integer;
2546
2547     case 'u':
2548       return g_variant_get_uint32 (value) == (guint32) tree->data.integer;
2549
2550     case 'x':
2551       return g_variant_get_int64 (value) == (gint64) tree->data.integer;
2552
2553     case 't':
2554       return g_variant_get_uint64 (value) == (guint64) tree->data.integer;
2555
2556     case 'h':
2557       return g_variant_get_handle (value) == (gint32) tree->data.integer;
2558
2559     case 'd':
2560       {
2561         gdouble floating = g_variant_get_double (value);
2562
2563         return memcmp (&floating, &tree->data.floating, sizeof floating) == 0;
2564       }
2565
2566     case 's':
2567     case 'o':
2568     case 'g':
2569       return strcmp (g_variant_get_string (value, NULL),
2570                      tree->data.string) == 0;
2571
2572     default:
2573       g_assert_not_reached ();
2574     }
2575 }
2576
2577 static void
2578 tree_instance_build_gvariant (TreeInstance    *tree,
2579                               GVariantBuilder *builder,
2580                               gboolean         guess_ok)
2581 {
2582   const GVariantType *type;
2583
2584   type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
2585
2586   if (g_variant_type_is_container (type))
2587     {
2588       gsize i;
2589
2590       /* force GVariantBuilder to guess the type half the time */
2591       if (guess_ok && randomly (0.5))
2592         {
2593           if (g_variant_type_is_array (type) && tree->n_children)
2594             type = G_VARIANT_TYPE_ARRAY;
2595
2596           if (g_variant_type_is_maybe (type) && tree->n_children)
2597             type = G_VARIANT_TYPE_MAYBE;
2598
2599           if (g_variant_type_is_tuple (type))
2600             type = G_VARIANT_TYPE_TUPLE;
2601
2602           if (g_variant_type_is_dict_entry (type))
2603             type = G_VARIANT_TYPE_DICT_ENTRY;
2604         }
2605       else
2606         guess_ok = FALSE;
2607
2608       g_variant_builder_open (builder, type);
2609
2610       for (i = 0; i < tree->n_children; i++)
2611         tree_instance_build_gvariant (tree->children[i], builder, guess_ok);
2612
2613       g_variant_builder_close (builder);
2614     }
2615   else
2616     g_variant_builder_add_value (builder, tree_instance_get_gvariant (tree));
2617 }
2618
2619
2620 static gboolean
2621 tree_instance_check_iter (TreeInstance *tree,
2622                           GVariantIter *iter)
2623 {
2624   GVariant *value;
2625
2626   value = g_variant_iter_next_value (iter);
2627
2628   if (g_variant_is_container (value))
2629     {
2630       gsize i;
2631
2632       iter = g_variant_iter_new (value);
2633       g_variant_unref (value);
2634
2635       if (g_variant_iter_n_children (iter) != tree->n_children)
2636         {
2637           g_variant_iter_free (iter);
2638           return FALSE;
2639         }
2640
2641       for (i = 0; i < tree->n_children; i++)
2642         if (!tree_instance_check_iter (tree->children[i], iter))
2643           {
2644             g_variant_iter_free (iter);
2645             return FALSE;
2646           }
2647
2648       g_assert (g_variant_iter_next_value (iter) == NULL);
2649       g_variant_iter_free (iter);
2650
2651       return TRUE;
2652     }
2653
2654   else
2655     {
2656       gboolean equal;
2657
2658       equal = tree_instance_check_gvariant (tree, value);
2659       g_variant_unref (value);
2660
2661       return equal;
2662     }
2663 }
2664
2665 static void
2666 test_container (void)
2667 {
2668   TreeInstance *tree;
2669   GVariant *value;
2670   gchar *s1, *s2;
2671
2672   tree = tree_instance_new (NULL, 3);
2673   value = g_variant_ref_sink (tree_instance_get_gvariant (tree));
2674
2675   s1 = g_variant_print (value, TRUE);
2676   g_assert (tree_instance_check_gvariant (tree, value));
2677
2678   g_variant_get_data (value);
2679
2680   s2 = g_variant_print (value, TRUE);
2681   g_assert (tree_instance_check_gvariant (tree, value));
2682
2683   g_assert_cmpstr (s1, ==, s2);
2684
2685   if (g_variant_is_container (value))
2686     {
2687       GVariantBuilder builder;
2688       GVariantIter iter;
2689       GVariant *built;
2690       GVariant *val;
2691       gchar *s3;
2692
2693       g_variant_builder_init (&builder, G_VARIANT_TYPE_VARIANT);
2694       tree_instance_build_gvariant (tree, &builder, TRUE);
2695       built = g_variant_builder_end (&builder);
2696       g_variant_ref_sink (built);
2697       g_variant_get_data (built);
2698       val = g_variant_get_variant (built);
2699
2700       s3 = g_variant_print (val, TRUE);
2701       g_assert_cmpstr (s1, ==, s3);
2702
2703       g_variant_iter_init (&iter, built);
2704       g_assert (tree_instance_check_iter (tree, &iter));
2705       g_assert (g_variant_iter_next_value (&iter) == NULL);
2706
2707       g_variant_unref (built);
2708       g_variant_unref (val);
2709       g_free (s3);
2710     }
2711
2712   tree_instance_free (tree);
2713   g_variant_unref (value);
2714   g_free (s2);
2715   g_free (s1);
2716 }
2717
2718 static void
2719 test_utf8 (void)
2720 {
2721   const gchar invalid[] = "hello\xffworld";
2722   GVariant *value;
2723
2724   /* ensure that the test data is not valid utf8... */
2725   g_assert (!g_utf8_validate (invalid, -1, NULL));
2726
2727   /* load the data untrusted */
2728   value = g_variant_new_from_data (G_VARIANT_TYPE_STRING,
2729                                    invalid, sizeof invalid,
2730                                    FALSE, NULL, NULL);
2731
2732   /* ensure that the problem is caught and we get valid UTF-8 */
2733   g_assert (g_utf8_validate (g_variant_get_string (value, NULL), -1, NULL));
2734   g_variant_unref (value);
2735
2736
2737   /* now load it trusted */
2738   value = g_variant_new_from_data (G_VARIANT_TYPE_STRING,
2739                                    invalid, sizeof invalid,
2740                                    TRUE, NULL, NULL);
2741
2742   /* ensure we get the invalid data (ie: make sure that time wasn't
2743    * wasted on validating data that was marked as trusted)
2744    */
2745   g_assert (g_variant_get_string (value, NULL) == invalid);
2746   g_variant_unref (value);
2747 }
2748
2749 static void
2750 test_containers (void)
2751 {
2752   gint i;
2753
2754   for (i = 0; i < 100; i++)
2755     {
2756       test_container ();
2757     }
2758
2759   g_variant_type_info_assert_no_infos ();
2760 }
2761
2762 static void
2763 test_format_strings (void)
2764 {
2765   GVariantType *type;
2766   const gchar *end;
2767
2768   g_assert (g_variant_format_string_scan ("i", NULL, &end) && *end == '\0');
2769   g_assert (g_variant_format_string_scan ("@i", NULL, &end) && *end == '\0');
2770   g_assert (g_variant_format_string_scan ("@ii", NULL, &end) && *end == 'i');
2771   g_assert (g_variant_format_string_scan ("^a&s", NULL, &end) && *end == '\0');
2772   g_assert (g_variant_format_string_scan ("(^as)", NULL, &end) &&
2773             *end == '\0');
2774   g_assert (!g_variant_format_string_scan ("(^s)", NULL, &end));
2775   g_assert (!g_variant_format_string_scan ("(^a)", NULL, &end));
2776   g_assert (!g_variant_format_string_scan ("(z)", NULL, &end));
2777   g_assert (!g_variant_format_string_scan ("az", NULL, &end));
2778   g_assert (!g_variant_format_string_scan ("{**}", NULL, &end));
2779   g_assert (!g_variant_format_string_scan ("{@**}", NULL, &end));
2780   g_assert (g_variant_format_string_scan ("{@y*}", NULL, &end) &&
2781             *end == '\0');
2782   g_assert (g_variant_format_string_scan ("{yv}", NULL, &end) &&
2783             *end == '\0');
2784   g_assert (!g_variant_format_string_scan ("{&?v}", NULL, &end));
2785   g_assert (g_variant_format_string_scan ("{@?v}", NULL, &end) &&
2786             *end == '\0');
2787   g_assert (!g_variant_format_string_scan ("{&@sv}", NULL, &end));
2788   g_assert (!g_variant_format_string_scan ("{@&sv}", NULL, &end));
2789   g_assert (g_variant_format_string_scan ("{&sv}", NULL, &end) &&
2790             *end == '\0');
2791   g_assert (!g_variant_format_string_scan ("{vv}", NULL, &end));
2792   g_assert (!g_variant_format_string_scan ("{y}", NULL, &end));
2793   g_assert (!g_variant_format_string_scan ("{yyy}", NULL, &end));
2794   g_assert (!g_variant_format_string_scan ("{ya}", NULL, &end));
2795   g_assert (g_variant_format_string_scan ("&s", NULL, &end) && *end == '\0');
2796   g_assert (!g_variant_format_string_scan ("&as", NULL, &end));
2797   g_assert (!g_variant_format_string_scan ("@z", NULL, &end));
2798   g_assert (!g_variant_format_string_scan ("az", NULL, &end));
2799   g_assert (!g_variant_format_string_scan ("a&s", NULL, &end));
2800
2801   type = g_variant_format_string_scan_type ("mm(@xy^a&s*?@?)", NULL, &end);
2802   g_assert (type && *end == '\0');
2803   g_assert (g_variant_type_equal (type, G_VARIANT_TYPE ("mm(xyas*?\?)")));
2804   g_variant_type_free (type);
2805
2806   type = g_variant_format_string_scan_type ("mm(@xy^a&*?@?)", NULL, NULL);
2807   g_assert (type == NULL);
2808 }
2809
2810 static void
2811 exit_on_abort (int signal)
2812 {
2813   exit (signal);
2814 }
2815
2816 static gboolean
2817 do_failed_test (const gchar *pattern)
2818 {
2819   if (g_test_trap_fork (1000000, G_TEST_TRAP_SILENCE_STDERR))
2820     {
2821       signal (SIGABRT, exit_on_abort);
2822       return TRUE;
2823     }
2824
2825   g_test_trap_assert_failed ();
2826   g_test_trap_assert_stderr (pattern);
2827
2828   return FALSE;
2829 }
2830
2831 static void
2832 test_invalid_varargs (void)
2833 {
2834   if (!g_test_undefined ())
2835     return;
2836
2837   if (do_failed_test ("*GVariant format string*"))
2838     {
2839       g_variant_new ("z");
2840       abort ();
2841     }
2842
2843   if (do_failed_test ("*valid GVariant format string as a prefix*"))
2844     {
2845       const gchar *end;
2846
2847       g_variant_new_va ("z", &end, NULL);
2848       abort ();
2849     }
2850
2851   if (do_failed_test ("*type of `q' but * has a type of `y'*"))
2852     {
2853       g_variant_get (g_variant_new ("y", 'a'), "q");
2854       abort ();
2855     }
2856 }
2857
2858 static void
2859 check_and_free (GVariant    *value,
2860                 const gchar *str)
2861 {
2862   gchar *valstr = g_variant_print (value, FALSE);
2863   g_assert_cmpstr (str, ==, valstr);
2864   g_variant_unref (value);
2865   g_free (valstr);
2866 }
2867
2868 static void
2869 test_varargs (void)
2870 {
2871   {
2872     GVariantBuilder array;
2873
2874     g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
2875     g_variant_builder_add_parsed (&array, "{'size', <(%i, %i)> }", 800, 600);
2876     g_variant_builder_add (&array, "{sv}", "title",
2877                            g_variant_new_string ("Test case"));
2878     g_variant_builder_add_value (&array,
2879       g_variant_new_dict_entry (g_variant_new_string ("temperature"),
2880                                 g_variant_new_variant (
2881                                   g_variant_new_double (37.5))));
2882     check_and_free (g_variant_new ("(ma{sv}m(a{sv})ma{sv}ii)",
2883                                    NULL, FALSE, NULL, &array, 7777, 8888),
2884                     "(nothing, nothing, {'size': <(800, 600)>, "
2885                                         "'title': <'Test case'>, "
2886                                         "'temperature': <37.5>}, "
2887                      "7777, 8888)");
2888
2889     check_and_free (g_variant_new ("(imimimmimmimmi)",
2890                                    123,
2891                                    FALSE, 321,
2892                                    TRUE, 123,
2893                                    FALSE, TRUE, 321,
2894                                    TRUE, FALSE, 321,
2895                                    TRUE, TRUE, 123),
2896                     "(123, nothing, 123, nothing, just nothing, 123)");
2897
2898     check_and_free (g_variant_new ("(ybnixd)",
2899                                    'a', 1, 22, 33, (guint64) 44, 5.5),
2900                     "(0x61, true, 22, 33, 44, 5.5)");
2901
2902     check_and_free (g_variant_new ("(@y?*rv)",
2903                                    g_variant_new ("y", 'a'),
2904                                    g_variant_new ("y", 'b'),
2905                                    g_variant_new ("y", 'c'),
2906                                    g_variant_new ("(y)", 'd'),
2907                                    g_variant_new ("y", 'e')),
2908                     "(0x61, 0x62, 0x63, (0x64,), <byte 0x65>)");
2909   }
2910
2911   {
2912     GVariantBuilder array;
2913     GVariantIter iter;
2914     GVariant *value;
2915     gchar *number;
2916     gboolean just;
2917     gint i, val;
2918
2919     g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
2920     for (i = 0; i < 100; i++)
2921       {
2922         number = g_strdup_printf ("%d", i);
2923         g_variant_builder_add (&array, "s", number);
2924         g_free (number);
2925       }
2926
2927     value = g_variant_builder_end (&array);
2928     g_variant_iter_init (&iter, value);
2929
2930     i = 0;
2931     while (g_variant_iter_loop (&iter, "s", &number))
2932       {
2933         gchar *check = g_strdup_printf ("%d", i++);
2934         g_assert_cmpstr (number, ==, check);
2935         g_free (check);
2936       }
2937     g_assert (number == NULL);
2938     g_assert (i == 100);
2939
2940     g_variant_unref (value);
2941
2942     g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
2943     for (i = 0; i < 100; i++)
2944       g_variant_builder_add (&array, "mi", i % 2 == 0, i);
2945     value = g_variant_builder_end (&array);
2946
2947     i = 0;
2948     g_variant_iter_init (&iter, value);
2949     while (g_variant_iter_loop (&iter, "mi", NULL, &val))
2950       g_assert (val == i++ || val == 0);
2951     g_assert (i == 100);
2952
2953     i = 0;
2954     g_variant_iter_init (&iter, value);
2955     while (g_variant_iter_loop (&iter, "mi", &just, &val))
2956       {
2957         gint this = i++;
2958
2959         if (this % 2 == 0)
2960           {
2961             g_assert (just);
2962             g_assert (val == this);
2963           }
2964         else
2965           {
2966             g_assert (!just);
2967             g_assert (val == 0);
2968           }
2969       }
2970     g_assert (i == 100);
2971
2972     g_variant_unref (value);
2973   }
2974
2975   {
2976     const gchar *strvector[] = {"/hello", "/world", NULL};
2977     const gchar *test_strs[] = {"/foo", "/bar", "/baz" };
2978     GVariantBuilder builder;
2979     GVariantIter *array;
2980     GVariantIter tuple;
2981     const gchar **strv;
2982     gchar **my_strv;
2983     GVariant *value;
2984     gchar *str;
2985     gint i;
2986
2987     g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
2988     g_variant_builder_add (&builder, "s", "/foo");
2989     g_variant_builder_add (&builder, "s", "/bar");
2990     g_variant_builder_add (&builder, "s", "/baz");
2991     value = g_variant_new("(as^as^a&s)", &builder, strvector, strvector);
2992     g_variant_iter_init (&tuple, value);
2993     g_variant_iter_next (&tuple, "as", &array);
2994
2995     i = 0;
2996     while (g_variant_iter_loop (array, "s", &str))
2997       g_assert_cmpstr (str, ==, test_strs[i++]);
2998     g_assert (i == 3);
2999
3000     g_variant_iter_free (array);
3001
3002     /* start over */
3003     g_variant_iter_init (&tuple, value);
3004     g_variant_iter_next (&tuple, "as", &array);
3005
3006     i = 0;
3007     while (g_variant_iter_loop (array, "&s", &str))
3008       g_assert_cmpstr (str, ==, test_strs[i++]);
3009     g_assert (i == 3);
3010
3011     g_variant_iter_free (array);
3012
3013     g_variant_iter_next (&tuple, "^a&s", &strv);
3014     g_variant_iter_next (&tuple, "^as", &my_strv);
3015
3016     g_assert_cmpstr (strv[0], ==, "/hello");
3017     g_assert_cmpstr (strv[1], ==, "/world");
3018     g_assert (strv[2] == NULL);
3019     g_assert_cmpstr (my_strv[0], ==, "/hello");
3020     g_assert_cmpstr (my_strv[1], ==, "/world");
3021     g_assert (my_strv[2] == NULL);
3022
3023     g_variant_unref (value);
3024     g_strfreev (my_strv);
3025     g_free (strv);
3026   }
3027
3028   {
3029     const gchar *strvector[] = {"/hello", "/world", NULL};
3030     const gchar *test_strs[] = {"/foo", "/bar", "/baz" };
3031     GVariantBuilder builder;
3032     GVariantIter *array;
3033     GVariantIter tuple;
3034     const gchar **strv;
3035     gchar **my_strv;
3036     GVariant *value;
3037     gchar *str;
3038     gint i;
3039
3040     g_variant_builder_init (&builder, G_VARIANT_TYPE_OBJECT_PATH_ARRAY);
3041     g_variant_builder_add (&builder, "o", "/foo");
3042     g_variant_builder_add (&builder, "o", "/bar");
3043     g_variant_builder_add (&builder, "o", "/baz");
3044     value = g_variant_new("(ao^ao^a&o)", &builder, strvector, strvector);
3045     g_variant_iter_init (&tuple, value);
3046     g_variant_iter_next (&tuple, "ao", &array);
3047
3048     i = 0;
3049     while (g_variant_iter_loop (array, "o", &str))
3050       g_assert_cmpstr (str, ==, test_strs[i++]);
3051     g_assert (i == 3);
3052
3053     g_variant_iter_free (array);
3054
3055     /* start over */
3056     g_variant_iter_init (&tuple, value);
3057     g_variant_iter_next (&tuple, "ao", &array);
3058
3059     i = 0;
3060     while (g_variant_iter_loop (array, "&o", &str))
3061       g_assert_cmpstr (str, ==, test_strs[i++]);
3062     g_assert (i == 3);
3063
3064     g_variant_iter_free (array);
3065
3066     g_variant_iter_next (&tuple, "^a&o", &strv);
3067     g_variant_iter_next (&tuple, "^ao", &my_strv);
3068
3069     g_assert_cmpstr (strv[0], ==, "/hello");
3070     g_assert_cmpstr (strv[1], ==, "/world");
3071     g_assert (strv[2] == NULL);
3072     g_assert_cmpstr (my_strv[0], ==, "/hello");
3073     g_assert_cmpstr (my_strv[1], ==, "/world");
3074     g_assert (my_strv[2] == NULL);
3075
3076     g_variant_unref (value);
3077     g_strfreev (my_strv);
3078     g_free (strv);
3079   }
3080
3081   {
3082     const gchar *strvector[] = { "i", "ii", "iii", "iv", "v", "vi", NULL };
3083     GVariantBuilder builder;
3084     GVariantIter iter;
3085     GVariantIter *i2;
3086     GVariantIter *i3;
3087     GVariant *value;
3088     GVariant *sub;
3089     gchar **strv;
3090     gint i;
3091
3092     g_variant_builder_init (&builder, G_VARIANT_TYPE ("aas"));
3093     g_variant_builder_open (&builder, G_VARIANT_TYPE ("as"));
3094     for (i = 0; i < 6; i++)
3095       if (i & 1)
3096         g_variant_builder_add (&builder, "s", strvector[i]);
3097       else
3098         g_variant_builder_add (&builder, "&s", strvector[i]);
3099     g_variant_builder_close (&builder);
3100     g_variant_builder_add (&builder, "^as", strvector);
3101     g_variant_builder_add (&builder, "^as", strvector);
3102     value = g_variant_new ("aas", &builder);
3103
3104     g_variant_iter_init (&iter, value);
3105     while (g_variant_iter_loop (&iter, "^as", &strv))
3106       for (i = 0; i < 6; i++)
3107         g_assert_cmpstr (strv[i], ==, strvector[i]);
3108
3109     g_variant_iter_init (&iter, value);
3110     while (g_variant_iter_loop (&iter, "^a&s", &strv))
3111       for (i = 0; i < 6; i++)
3112         g_assert_cmpstr (strv[i], ==, strvector[i]);
3113
3114     g_variant_iter_init (&iter, value);
3115     while (g_variant_iter_loop (&iter, "as", &i2))
3116       {
3117         gchar *str;
3118
3119         i = 0;
3120         while (g_variant_iter_loop (i2, "s", &str))
3121           g_assert_cmpstr (str, ==, strvector[i++]);
3122         g_assert (i == 6);
3123       }
3124
3125     g_variant_iter_init (&iter, value);
3126     i3 = g_variant_iter_copy (&iter);
3127     while (g_variant_iter_loop (&iter, "@as", &sub))
3128       {
3129         gchar *str = g_variant_print (sub, TRUE);
3130         g_assert_cmpstr (str, ==,
3131                          "['i', 'ii', 'iii', 'iv', 'v', 'vi']");
3132         g_free (str);
3133       }
3134
3135   if (do_failed_test ("*NULL has already been returned*"))
3136     {
3137       g_variant_iter_next_value (&iter);
3138       abort ();
3139     }
3140
3141
3142     while (g_variant_iter_loop (i3, "*", &sub))
3143       {
3144         gchar *str = g_variant_print (sub, TRUE);
3145         g_assert_cmpstr (str, ==,
3146                          "['i', 'ii', 'iii', 'iv', 'v', 'vi']");
3147         g_free (str);
3148       }
3149
3150     g_variant_iter_free (i3);
3151
3152     for (i = 0; i < g_variant_n_children (value); i++)
3153       {
3154         gint j;
3155
3156         g_variant_get_child (value, i, "*", &sub);
3157
3158         for (j = 0; j < g_variant_n_children (sub); j++)
3159           {
3160             const gchar *str = NULL;
3161             GVariant *cval;
3162
3163             g_variant_get_child (sub, j, "&s", &str);
3164             g_assert_cmpstr (str, ==, strvector[j]);
3165
3166             cval = g_variant_get_child_value (sub, j);
3167             g_variant_get (cval, "&s", &str);
3168             g_assert_cmpstr (str, ==, strvector[j]);
3169             g_variant_unref (cval);
3170           }
3171
3172         g_variant_unref (sub);
3173       }
3174
3175     g_variant_unref (value);
3176   }
3177
3178   {
3179     gboolean justs[10];
3180     GVariant *value;
3181
3182     GVariant *vval;
3183     guchar byteval;
3184     gboolean bval;
3185     gint16 i16val;
3186     guint16 u16val;
3187     gint32 i32val;
3188     guint32 u32val;
3189     gint64 i64val;
3190     guint64 u64val;
3191     gdouble dval;
3192     gint32 hval;
3193
3194     /* test all 'nothing' */
3195     value = g_variant_new ("(mymbmnmqmimumxmtmhmdmv)",
3196                            FALSE, 'a',
3197                            FALSE, TRUE,
3198                            FALSE, (gint16) 123,
3199                            FALSE, (guint16) 123,
3200                            FALSE, (gint32) 123,
3201                            FALSE, (guint32) 123,
3202                            FALSE, (gint64) 123,
3203                            FALSE, (guint64) 123,
3204                            FALSE, (gint32) -1,
3205                            FALSE, (gdouble) 37.5,
3206                            NULL);
3207
3208     /* both NULL */
3209     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3210                    NULL, NULL,
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);
3221
3222     /* NULL values */
3223     memset (justs, 1, sizeof justs);
3224     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3225                    &justs[0], NULL,
3226                    &justs[1], NULL,
3227                    &justs[2], NULL,
3228                    &justs[3], NULL,
3229                    &justs[4], NULL,
3230                    &justs[5], NULL,
3231                    &justs[6], NULL,
3232                    &justs[7], NULL,
3233                    &justs[8], NULL,
3234                    &justs[9], NULL,
3235                    NULL);
3236     g_assert (!(justs[0] || justs[1] || justs[2] || justs[3] || justs[4] ||
3237                 justs[5] || justs[6] || justs[7] || justs[8] || justs[9]));
3238
3239     /* both non-NULL */
3240     memset (justs, 1, sizeof justs);
3241     byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3242     vval = (void *) 1;
3243     bval = TRUE;
3244     dval = 88.88;
3245     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3246                    &justs[0], &byteval,
3247                    &justs[1], &bval,
3248                    &justs[2], &i16val,
3249                    &justs[3], &u16val,
3250                    &justs[4], &i32val,
3251                    &justs[5], &u32val,
3252                    &justs[6], &i64val,
3253                    &justs[7], &u64val,
3254                    &justs[8], &hval,
3255                    &justs[9], &dval,
3256                    &vval);
3257     g_assert (!(justs[0] || justs[1] || justs[2] || justs[3] || justs[4] ||
3258                 justs[5] || justs[6] || justs[7] || justs[8] || justs[9]));
3259     g_assert (byteval == '\0' && bval == FALSE);
3260     g_assert (i16val == 0 && u16val == 0 && i32val == 0 &&
3261               u32val == 0 && i64val == 0 && u64val == 0 &&
3262               hval == 0 && dval == 0.0);
3263     g_assert (vval == NULL);
3264
3265     /* NULL justs */
3266     byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3267     vval = (void *) 1;
3268     bval = TRUE;
3269     dval = 88.88;
3270     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3271                    NULL, &byteval,
3272                    NULL, &bval,
3273                    NULL, &i16val,
3274                    NULL, &u16val,
3275                    NULL, &i32val,
3276                    NULL, &u32val,
3277                    NULL, &i64val,
3278                    NULL, &u64val,
3279                    NULL, &hval,
3280                    NULL, &dval,
3281                    &vval);
3282     g_assert (byteval == '\0' && bval == FALSE);
3283     g_assert (i16val == 0 && u16val == 0 && i32val == 0 &&
3284               u32val == 0 && i64val == 0 && u64val == 0 &&
3285               hval == 0 && dval == 0.0);
3286     g_assert (vval == NULL);
3287
3288     g_variant_unref (value);
3289
3290
3291     /* test all 'just' */
3292     value = g_variant_new ("(mymbmnmqmimumxmtmhmdmv)",
3293                            TRUE, 'a',
3294                            TRUE, TRUE,
3295                            TRUE, (gint16) 123,
3296                            TRUE, (guint16) 123,
3297                            TRUE, (gint32) 123,
3298                            TRUE, (guint32) 123,
3299                            TRUE, (gint64) 123,
3300                            TRUE, (guint64) 123,
3301                            TRUE, (gint32) -1,
3302                            TRUE, (gdouble) 37.5,
3303                            g_variant_new ("()"));
3304
3305     /* both NULL */
3306     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3307                    NULL, NULL,
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);
3318
3319     /* NULL values */
3320     memset (justs, 0, sizeof justs);
3321     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3322                    &justs[0], NULL,
3323                    &justs[1], NULL,
3324                    &justs[2], NULL,
3325                    &justs[3], NULL,
3326                    &justs[4], NULL,
3327                    &justs[5], NULL,
3328                    &justs[6], NULL,
3329                    &justs[7], NULL,
3330                    &justs[8], NULL,
3331                    &justs[9], NULL,
3332                    NULL);
3333     g_assert (justs[0] && justs[1] && justs[2] && justs[3] && justs[4] &&
3334               justs[5] && justs[6] && justs[7] && justs[8] && justs[9]);
3335
3336     /* both non-NULL */
3337     memset (justs, 0, sizeof justs);
3338     byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3339     vval = (void *) 1;
3340     bval = FALSE;
3341     dval = 88.88;
3342     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3343                    &justs[0], &byteval,
3344                    &justs[1], &bval,
3345                    &justs[2], &i16val,
3346                    &justs[3], &u16val,
3347                    &justs[4], &i32val,
3348                    &justs[5], &u32val,
3349                    &justs[6], &i64val,
3350                    &justs[7], &u64val,
3351                    &justs[8], &hval,
3352                    &justs[9], &dval,
3353                    &vval);
3354     g_assert (justs[0] && justs[1] && justs[2] && justs[3] && justs[4] &&
3355               justs[5] && justs[6] && justs[7] && justs[8] && justs[9]);
3356     g_assert (byteval == 'a' && bval == TRUE);
3357     g_assert (i16val == 123 && u16val == 123 && i32val == 123 &&
3358               u32val == 123 && i64val == 123 && u64val == 123 &&
3359               hval == -1 && dval == 37.5);
3360     g_assert (g_variant_is_of_type (vval, G_VARIANT_TYPE_UNIT));
3361     g_variant_unref (vval);
3362
3363     /* NULL justs */
3364     byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3365     vval = (void *) 1;
3366     bval = TRUE;
3367     dval = 88.88;
3368     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3369                    NULL, &byteval,
3370                    NULL, &bval,
3371                    NULL, &i16val,
3372                    NULL, &u16val,
3373                    NULL, &i32val,
3374                    NULL, &u32val,
3375                    NULL, &i64val,
3376                    NULL, &u64val,
3377                    NULL, &hval,
3378                    NULL, &dval,
3379                    &vval);
3380     g_assert (byteval == 'a' && bval == TRUE);
3381     g_assert (i16val == 123 && u16val == 123 && i32val == 123 &&
3382               u32val == 123 && i64val == 123 && u64val == 123 &&
3383               hval == -1 && dval == 37.5);
3384     g_assert (g_variant_is_of_type (vval, G_VARIANT_TYPE_UNIT));
3385     g_variant_unref (vval);
3386
3387     g_variant_unref (value);
3388   }
3389
3390   {
3391     GVariant *value;
3392     gchar *str;
3393
3394     value = g_variant_new ("(masas)", NULL, NULL);
3395     g_variant_ref_sink (value);
3396
3397     str = g_variant_print (value, TRUE);
3398     g_assert_cmpstr (str, ==, "(@mas nothing, @as [])");
3399     g_variant_unref (value);
3400     g_free (str);
3401
3402     if (do_failed_test ("*which type of empty array*"))
3403       g_variant_new ("(a{s*})", NULL);
3404   }
3405
3406   g_variant_type_info_assert_no_infos ();
3407 }
3408
3409 static void
3410 hash_get (GVariant    *value,
3411           const gchar *format,
3412           ...)
3413 {
3414   const gchar *endptr = NULL;
3415   gboolean hash;
3416   va_list ap;
3417
3418   hash = g_str_has_suffix (format, "#");
3419
3420   va_start (ap, format);
3421   g_variant_get_va (value, format, hash ? &endptr : NULL, &ap);
3422   va_end (ap);
3423
3424   if (hash)
3425     g_assert (*endptr == '#');
3426 }
3427
3428 static GVariant *
3429 hash_new (const gchar *format,
3430           ...)
3431 {
3432   const gchar *endptr = NULL;
3433   GVariant *value;
3434   gboolean hash;
3435   va_list ap;
3436
3437   hash = g_str_has_suffix (format, "#");
3438
3439   va_start (ap, format);
3440   value = g_variant_new_va (format, hash ? &endptr : NULL, &ap);
3441   va_end (ap);
3442
3443   if (hash)
3444     g_assert (*endptr == '#');
3445
3446   return value;
3447 }
3448
3449 static void
3450 test_valist (void)
3451 {
3452   GVariant *value;
3453   gint32 x;
3454
3455   x = 0;
3456   value = hash_new ("i", 234);
3457   hash_get (value, "i", &x);
3458   g_assert (x == 234);
3459   g_variant_unref (value);
3460
3461   x = 0;
3462   value = hash_new ("i#", 234);
3463   hash_get (value, "i#", &x);
3464   g_assert (x == 234);
3465   g_variant_unref (value);
3466
3467   g_variant_type_info_assert_no_infos ();
3468 }
3469
3470 static void
3471 test_builder_memory (void)
3472 {
3473   GVariantBuilder *hb;
3474   GVariantBuilder sb;
3475
3476   hb = g_variant_builder_new  (G_VARIANT_TYPE_ARRAY);
3477   g_variant_builder_open (hb, 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_add (hb, "s", "some value");
3481   g_variant_builder_ref (hb);
3482   g_variant_builder_unref (hb);
3483   g_variant_builder_unref (hb);
3484
3485   hb = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
3486   g_variant_builder_unref (hb);
3487
3488   hb = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
3489   g_variant_builder_clear (hb);
3490   g_variant_builder_unref (hb);
3491
3492   g_variant_builder_init (&sb, G_VARIANT_TYPE_ARRAY);
3493   g_variant_builder_open (&sb, G_VARIANT_TYPE_ARRAY);
3494   g_variant_builder_open (&sb, G_VARIANT_TYPE_ARRAY);
3495   g_variant_builder_add (&sb, "s", "some value");
3496   g_variant_builder_clear (&sb);
3497
3498   g_variant_type_info_assert_no_infos ();
3499 }
3500
3501 static void
3502 test_hashing (void)
3503 {
3504   GVariant *items[4096];
3505   GHashTable *table;
3506   gint i;
3507
3508   table = g_hash_table_new_full (g_variant_hash, g_variant_equal,
3509                                  (GDestroyNotify ) g_variant_unref,
3510                                  NULL);
3511
3512   for (i = 0; i < G_N_ELEMENTS (items); i++)
3513     {
3514       TreeInstance *tree;
3515       gint j;
3516
3517  again:
3518       tree = tree_instance_new (NULL, 0);
3519       items[i] = tree_instance_get_gvariant (tree);
3520       tree_instance_free (tree);
3521
3522       for (j = 0; j < i; j++)
3523         if (g_variant_equal (items[i], items[j]))
3524           {
3525             g_variant_unref (items[i]);
3526             goto again;
3527           }
3528
3529       g_hash_table_insert (table,
3530                            g_variant_ref_sink (items[i]),
3531                            GINT_TO_POINTER (i));
3532     }
3533
3534   for (i = 0; i < G_N_ELEMENTS (items); i++)
3535     {
3536       gpointer result;
3537
3538       result = g_hash_table_lookup (table, items[i]);
3539       g_assert_cmpint (GPOINTER_TO_INT (result), ==, i);
3540     }
3541
3542   g_hash_table_unref (table);
3543
3544   g_variant_type_info_assert_no_infos ();
3545 }
3546
3547 static void
3548 test_gv_byteswap ()
3549 {
3550 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
3551 # define native16(x)  x, 0
3552 # define swapped16(x) 0, x
3553 #else
3554 # define native16(x)  0, x
3555 # define swapped16(x) x, 0
3556 #endif
3557   /* all kinds of of crazy randomised testing already performed on the
3558    * byteswapper in the /gvariant/serialiser/byteswap test and all kinds
3559    * of crazy randomised testing performed against the serialiser
3560    * normalisation functions in the /gvariant/serialiser/fuzz/ tests.
3561    *
3562    * just test a few simple cases here to make sure they each work
3563    */
3564   guchar validbytes[] = { 'a', '\0', swapped16(66), 2,
3565                           0,
3566                           'b', '\0', swapped16(77), 2,
3567                           5, 11 };
3568   guchar corruptbytes[] = { 'a', '\0', swapped16(66), 2,
3569                             0,
3570                             'b', '\0', swapped16(77), 2,
3571                             6, 11 };
3572   guint valid_data[4], corrupt_data[4];
3573   GVariant *value, *swapped;
3574   gchar *string, *string2;
3575
3576   memcpy (valid_data, validbytes, sizeof validbytes);
3577   memcpy (corrupt_data, corruptbytes, sizeof corruptbytes);
3578
3579   /* trusted */
3580   value = g_variant_new_from_data (G_VARIANT_TYPE ("a(sn)"),
3581                                    valid_data, sizeof validbytes, TRUE,
3582                                    NULL, NULL);
3583   swapped = g_variant_byteswap (value);
3584   g_variant_unref (value);
3585   g_assert (g_variant_get_size (swapped) == 13);
3586   string = g_variant_print (swapped, FALSE);
3587   g_variant_unref (swapped);
3588   g_assert_cmpstr (string, ==, "[('a', 66), ('b', 77)]");
3589   g_free (string);
3590
3591   /* untrusted but valid */
3592   value = g_variant_new_from_data (G_VARIANT_TYPE ("a(sn)"),
3593                                    valid_data, sizeof validbytes, FALSE,
3594                                    NULL, NULL);
3595   swapped = g_variant_byteswap (value);
3596   g_variant_unref (value);
3597   g_assert (g_variant_get_size (swapped) == 13);
3598   string = g_variant_print (swapped, FALSE);
3599   g_variant_unref (swapped);
3600   g_assert_cmpstr (string, ==, "[('a', 66), ('b', 77)]");
3601   g_free (string);
3602
3603   /* untrusted, invalid */
3604   value = g_variant_new_from_data (G_VARIANT_TYPE ("a(sn)"),
3605                                    corrupt_data, sizeof corruptbytes, FALSE,
3606                                    NULL, NULL);
3607   string = g_variant_print (value, FALSE);
3608   swapped = g_variant_byteswap (value);
3609   g_variant_unref (value);
3610   g_assert (g_variant_get_size (swapped) == 13);
3611   value = g_variant_byteswap (swapped);
3612   g_variant_unref (swapped);
3613   string2 = g_variant_print (value, FALSE);
3614   g_assert (g_variant_get_size (value) == 13);
3615   g_variant_unref (value);
3616   g_assert_cmpstr (string, ==, string2);
3617   g_free (string2);
3618   g_free (string);
3619 }
3620
3621 static void
3622 test_parser (void)
3623 {
3624   TreeInstance *tree;
3625   GVariant *parsed;
3626   GVariant *value;
3627   gchar *pt, *p;
3628   gchar *res;
3629
3630   tree = tree_instance_new (NULL, 3);
3631   value = tree_instance_get_gvariant (tree);
3632   tree_instance_free (tree);
3633
3634   pt = g_variant_print (value, TRUE);
3635   p = g_variant_print (value, FALSE);
3636
3637   parsed = g_variant_parse (NULL, pt, NULL, NULL, NULL);
3638   res = g_variant_print (parsed, FALSE);
3639   g_assert_cmpstr (p, ==, res);
3640   g_variant_unref (parsed);
3641   g_free (res);
3642
3643   parsed = g_variant_parse (g_variant_get_type (value), p,
3644                             NULL, NULL, NULL);
3645   res = g_variant_print (parsed, TRUE);
3646   g_assert_cmpstr (pt, ==, res);
3647   g_variant_unref (parsed);
3648   g_free (res);
3649
3650   g_variant_unref (value);
3651   g_free (pt);
3652   g_free (p);
3653 }
3654
3655 static void
3656 test_parses (void)
3657 {
3658   gint i;
3659
3660   for (i = 0; i < 100; i++)
3661     {
3662       test_parser ();
3663     }
3664
3665   /* mini test */
3666   {
3667     GError *error = NULL;
3668     gchar str[128];
3669     GVariant *val;
3670     gchar *p, *p2;
3671
3672     for (i = 0; i < 127; i++)
3673       str[i] = i + 1;
3674     str[i] = 0;
3675
3676     val = g_variant_new_string (str);
3677     p = g_variant_print (val, FALSE);
3678     g_variant_unref (val);
3679
3680     val = g_variant_parse (NULL, p, NULL, NULL, &error);
3681     p2 = g_variant_print (val, FALSE);
3682
3683     g_assert_cmpstr (str, ==, g_variant_get_string (val, NULL));
3684     g_assert_cmpstr (p, ==, p2);
3685
3686     g_variant_unref (val);
3687     g_free (p2);
3688     g_free (p);
3689   }
3690
3691   /* another mini test */
3692   {
3693     const gchar *end;
3694     GVariant *value;
3695
3696     value = g_variant_parse (G_VARIANT_TYPE_INT32, "1 2 3", NULL, &end, NULL);
3697     g_assert_cmpint (g_variant_get_int32 (value), ==, 1);
3698     /* make sure endptr returning works */
3699     g_assert_cmpstr (end, ==, " 2 3");
3700     g_variant_unref (value);
3701   }
3702
3703   /* unicode mini test */
3704   {
3705     /* ał𝄞 */
3706     const gchar orig[] = "a\xc5\x82\xf0\x9d\x84\x9e \t\n";
3707     GVariant *value;
3708     gchar *printed;
3709
3710     value = g_variant_new_string (orig);
3711     printed = g_variant_print (value, FALSE);
3712     g_variant_unref (value);
3713
3714     g_assert_cmpstr (printed, ==, "'a\xc5\x82\xf0\x9d\x84\x9e \\t\\n'");
3715     value = g_variant_parse (NULL, printed, NULL, NULL, NULL);
3716     g_assert_cmpstr (g_variant_get_string (value, NULL), ==, orig);
3717     g_variant_unref (value);
3718     g_free (printed);
3719   }
3720
3721   /* inf/nan mini test */
3722   {
3723     const gchar *tests[] = { "inf", "-inf", "nan" };
3724     GVariant *value;
3725     gchar *printed;
3726     gint i;
3727
3728     for (i = 0; i < G_N_ELEMENTS (tests); i++)
3729       {
3730         GError *error = NULL;
3731         value = g_variant_parse (NULL, tests[i], NULL, NULL, &error);
3732         printed = g_variant_print (value, FALSE);
3733         g_assert (g_str_has_prefix (printed, tests[i]));
3734         g_free (printed);
3735         g_variant_unref (value);
3736       }
3737   }
3738
3739   g_variant_type_info_assert_no_infos ();
3740 }
3741
3742 static void
3743 test_parse_failures (void)
3744 {
3745   const gchar *test[] = {
3746     "[1, 2,",                   "6:",              "expected value",
3747     "",                         "0:",              "expected value",
3748     "(1, 2,",                   "6:",              "expected value",
3749     "<1",                       "2:",              "expected `>'",
3750     "[]",                       "0-2:",            "unable to infer",
3751     "(,",                       "1:",              "expected value",
3752     "[4,'']",                   "1-2,3-5:",        "common type",
3753     "[4, '', 5]",               "1-2,4-6:",        "common type",
3754     "['', 4, 5]",               "1-3,5-6:",        "common type",
3755     "[4, 5, '']",               "1-2,7-9:",        "common type",
3756     "[[4], [], ['']]",          "1-4,10-14:",      "common type",
3757     "[[], [4], ['']]",          "5-8,10-14:",      "common type",
3758     "just",                     "4:",              "expected value",
3759     "nothing",                  "0-7:",            "unable to infer",
3760     "just [4, '']",             "6-7,9-11:",       "common type",
3761     "[[4,'']]",                 "2-3,4-6:",        "common type",
3762     "([4,''],)",                "2-3,4-6:",        "common type",
3763     "(4)",                      "2:",              "`,'",
3764     "{}",                       "0-2:",            "unable to infer",
3765     "{[1,2],[3,4]}",            "0-13:",           "basic types",
3766     "{[1,2]:[3,4]}",            "0-13:",           "basic types",
3767     "justt",                    "0-5:",            "unknown keyword",
3768     "nothng",                   "0-6:",            "unknown keyword",
3769     "uint33",                   "0-6:",            "unknown keyword",
3770     "@mi just ''",              "9-11:",           "can not parse as",
3771     "@ai ['']",                 "5-7:",            "can not parse as",
3772     "@(i) ('',)",               "6-8:",            "can not parse as",
3773     "[[], 5]",                  "1-3,5-6:",        "common type",
3774     "[[5], 5]",                 "1-4,6-7:",        "common type",
3775     "5 5",                      "2:",              "expected end of input",
3776     "[5, [5, '']]",             "5-6,8-10:",       "common type",
3777     "@i just 5",                "3-9:",            "can not parse as",
3778     "@i nothing",               "3-10:",           "can not parse as",
3779     "@i []",                    "3-5:",            "can not parse as",
3780     "@i ()",                    "3-5:",            "can not parse as",
3781     "@ai (4,)",                 "4-8:",            "can not parse as",
3782     "@(i) []",                  "5-7:",            "can not parse as",
3783     "(5 5)",                    "3:",              "expected `,'",
3784     "[5 5]",                    "3:",              "expected `,' or `]'",
3785     "(5, 5 5)",                 "6:",              "expected `,' or `)'",
3786     "[5, 5 5]",                 "6:",              "expected `,' or `]'",
3787     "<@i []>",                  "4-6:",            "can not parse as",
3788     "<[5 5]>",                  "4:",              "expected `,' or `]'",
3789     "{[4,''],5}",               "2-3,4-6:",        "common type",
3790     "{5,[4,'']}",               "4-5,6-8:",        "common type",
3791     "@i {1,2}",                 "3-8:",            "can not parse as",
3792     "{@i '', 5}",               "4-6:",            "can not parse as",
3793     "{5, @i ''}",               "7-9:",            "can not parse as",
3794     "@ai {}",                   "4-6:",            "can not parse as",
3795     "{@i '': 5}",               "4-6:",            "can not parse as",
3796     "{5: @i ''}",               "7-9:",            "can not parse as",
3797     "{<4,5}",                   "3:",              "expected `>'",
3798     "{4,<5}",                   "5:",              "expected `>'",
3799     "{4,5,6}",                  "4:",              "expected `}'",
3800     "{5 5}",                    "3:",              "expected `:' or `,'",
3801     "{4: 5: 6}",                "5:",              "expected `,' or `}'",
3802     "{4:5,<6:7}",               "7:",              "expected `>'",
3803     "{4:5,6:<7}",               "9:",              "expected `>'",
3804     "{4:5,6 7}",                "7:",              "expected `:'",
3805     "@o 'foo'",                 "3-8:",            "object path",
3806     "@g 'zzz'",                 "3-8:",            "signature",
3807     "@i true",                  "3-7:",            "can not parse as",
3808     "@z 4",                     "0-2:",            "invalid type",
3809     "@a* []",                   "0-3:",            "definite",
3810     "@ai [3 3]",                "7:",              "expected `,' or `]'",
3811     "18446744073709551616",     "0-20:",           "too big for any type",
3812     "-18446744073709551616",    "0-21:",           "too big for any type",
3813     "byte 256",                 "5-8:",            "out of range for type",
3814     "byte -1",                  "5-7:",            "out of range for type",
3815     "int16 32768",              "6-11:",           "out of range for type",
3816     "int16 -32769",             "6-12:",           "out of range for type",
3817     "uint16 -1",                "7-9:",            "out of range for type",
3818     "uint16 65536",             "7-12:",           "out of range for type",
3819     "2147483648",               "0-10:",           "out of range for type",
3820     "-2147483649",              "0-11:",           "out of range for type",
3821     "uint32 -1",                "7-9:",            "out of range for type",
3822     "uint32 4294967296",        "7-17:",           "out of range for type",
3823     "@x 9223372036854775808",   "3-22:",           "out of range for type",
3824     "@x -9223372036854775809",  "3-23:",           "out of range for type",
3825     "@t -1",                    "3-5:",            "out of range for type",
3826     "@t 18446744073709551616",  "3-23:",           "too big for any type",
3827     "handle 2147483648",        "7-17:",           "out of range for type",
3828     "handle -2147483649",       "7-18:",           "out of range for type",
3829     "1.798e308",                "0-9:",            "too big for any type",
3830     "37.5a488",                 "4-5:",            "invalid character",
3831     "0x7ffgf",                  "5-6:",            "invalid character",
3832     "07758",                    "4-5:",            "invalid character",
3833     "123a5",                    "3-4:",            "invalid character",
3834     "@ai 123",                  "4-7:",            "can not parse as",
3835     "'\"\\'",                   "0-4:",            "unterminated string",
3836     "'\"\\'\\",                 "0-5:",            "unterminated string",
3837     "boolean 4",                "8-9:",            "can not parse as",
3838     "int32 true",               "6-10:",           "can not parse as",
3839     "[double 5, int32 5]",      "1-9,11-18:",      "common type",
3840     "string 4",                 "7-8:",            "can not parse as"
3841   };
3842   gint i;
3843
3844   for (i = 0; i < G_N_ELEMENTS (test); i += 3)
3845     {
3846       GError *error = NULL;
3847       GVariant *value;
3848
3849       value = g_variant_parse (NULL, test[i], NULL, NULL, &error);
3850       g_assert (value == NULL);
3851
3852       if (!strstr (error->message, test[i+2]))
3853         g_error ("test %d: Can't find `%s' in `%s'", i / 3,
3854                  test[i+2], error->message);
3855
3856       if (!g_str_has_prefix (error->message, test[i+1]))
3857         g_error ("test %d: Expected location `%s' in `%s'", i / 3,
3858                  test[i+1], error->message);
3859
3860       g_error_free (error);
3861     }
3862 }
3863
3864 static void
3865 test_parse_positional (void)
3866 {
3867   GVariant *value;
3868   check_and_free (g_variant_new_parsed ("[('one', 1), (%s, 2),"
3869                                         " ('three', %i)]", "two", 3),
3870                   "[('one', 1), ('two', 2), ('three', 3)]");
3871   value = g_variant_new_parsed ("[('one', 1), (%s, 2),"
3872                                 " ('three', %u)]", "two", 3);
3873   g_assert (g_variant_is_of_type (value, G_VARIANT_TYPE ("a(su)")));
3874   check_and_free (value, "[('one', 1), ('two', 2), ('three', 3)]");
3875   check_and_free (g_variant_new_parsed ("{%s:%i}", "one", 1), "{'one': 1}");
3876
3877   if (g_test_undefined ())
3878     {
3879       if (do_failed_test ("*GVariant format string*"))
3880         {
3881           g_variant_new_parsed ("%z");
3882           abort ();
3883         }
3884
3885       if (do_failed_test ("*can not parse as*"))
3886         {
3887           g_variant_new_parsed ("uint32 %i", 2);
3888           abort ();
3889         }
3890
3891       if (do_failed_test ("*expected GVariant of type `i'*"))
3892         {
3893           g_variant_new_parsed ("%@i", g_variant_new_uint32 (2));
3894           abort ();
3895         }
3896     }
3897 }
3898
3899 static void
3900 test_floating (void)
3901 {
3902   GVariant *value;
3903
3904   value = g_variant_new_int32 (42);
3905   g_assert (g_variant_is_floating (value));
3906   g_variant_ref_sink (value);
3907   g_assert (!g_variant_is_floating (value));
3908   g_variant_unref (value);
3909 }
3910
3911 static void
3912 test_bytestring (void)
3913 {
3914   const gchar *test_string = "foo,bar,baz,quux,\xffoooo";
3915   GVariant *value;
3916   gchar **strv;
3917   gchar *str;
3918   const gchar *const_str;
3919   GVariant *untrusted_empty;
3920
3921   strv = g_strsplit (test_string, ",", 0);
3922
3923   value = g_variant_new_bytestring_array ((const gchar **) strv, -1);
3924   g_assert (g_variant_is_floating (value));
3925   g_strfreev (strv);
3926
3927   str = g_variant_print (value, FALSE);
3928   g_variant_unref (value);
3929
3930   value = g_variant_parse (NULL, str, NULL, NULL, NULL);
3931   g_free (str);
3932
3933   strv = g_variant_dup_bytestring_array (value, NULL);
3934   g_variant_unref (value);
3935
3936   str = g_strjoinv (",", strv);
3937   g_strfreev (strv);
3938
3939   g_assert_cmpstr (str, ==, test_string);
3940   g_free (str);
3941
3942   strv = g_strsplit (test_string, ",", 0);
3943   value = g_variant_new ("(^aay^a&ay^ay^&ay)",
3944                          strv, strv, strv[0], strv[0]);
3945   g_strfreev (strv);
3946
3947   g_variant_get_child (value, 0, "^a&ay", &strv);
3948   str = g_strjoinv (",", strv);
3949   g_free (strv);
3950   g_assert_cmpstr (str, ==, test_string);
3951   g_free (str);
3952
3953   g_variant_get_child (value, 0, "^aay", &strv);
3954   str = g_strjoinv (",", strv);
3955   g_strfreev (strv);
3956   g_assert_cmpstr (str, ==, test_string);
3957   g_free (str);
3958
3959   g_variant_get_child (value, 1, "^a&ay", &strv);
3960   str = g_strjoinv (",", strv);
3961   g_free (strv);
3962   g_assert_cmpstr (str, ==, test_string);
3963   g_free (str);
3964
3965   g_variant_get_child (value, 1, "^aay", &strv);
3966   str = g_strjoinv (",", strv);
3967   g_strfreev (strv);
3968   g_assert_cmpstr (str, ==, test_string);
3969   g_free (str);
3970
3971   g_variant_get_child (value, 2, "^ay", &str);
3972   g_assert_cmpstr (str, ==, "foo");
3973   g_free (str);
3974
3975   g_variant_get_child (value, 2, "^&ay", &str);
3976   g_assert_cmpstr (str, ==, "foo");
3977
3978   g_variant_get_child (value, 3, "^ay", &str);
3979   g_assert_cmpstr (str, ==, "foo");
3980   g_free (str);
3981
3982   g_variant_get_child (value, 3, "^&ay", &str);
3983   g_assert_cmpstr (str, ==, "foo");
3984   g_variant_unref (value);
3985
3986   untrusted_empty = g_variant_new_from_data (G_VARIANT_TYPE ("ay"), NULL, 0, FALSE, NULL, NULL);
3987   value = g_variant_get_normal_form (untrusted_empty);
3988   const_str = g_variant_get_bytestring (value);
3989   (void) const_str;
3990   g_variant_unref (value);
3991   g_variant_unref (untrusted_empty);
3992 }
3993
3994 static void
3995 test_lookup_value (void)
3996 {
3997   struct {
3998     const gchar *dict, *key, *value;
3999   } cases[] = {
4000     { "@a{ss} {'x':  'y'}",   "x",  "'y'" },
4001     { "@a{ss} {'x':  'y'}",   "y"         },
4002     { "@a{os} {'/x': 'y'}",   "/x", "'y'" },
4003     { "@a{os} {'/x': 'y'}",   "/y"        },
4004     { "@a{sv} {'x':  <'y'>}", "x",  "'y'" },
4005     { "@a{sv} {'x':  <5>}",   "x",  "5"   },
4006     { "@a{sv} {'x':  <'y'>}", "y"         }
4007   };
4008   gint i;
4009
4010   for (i = 0; i < G_N_ELEMENTS (cases); i++)
4011     {
4012       GVariant *dictionary;
4013       GVariant *value;
4014       gchar *p;
4015       
4016       dictionary = g_variant_parse (NULL, cases[i].dict, NULL, NULL, NULL);
4017       value = g_variant_lookup_value (dictionary, cases[i].key, NULL);
4018       g_variant_unref (dictionary);
4019
4020       if (value == NULL && cases[i].value == NULL)
4021         continue;
4022
4023       g_assert (value && cases[i].value);
4024       p = g_variant_print (value, FALSE);
4025       g_assert_cmpstr (cases[i].value, ==, p);
4026       g_variant_unref (value);
4027       g_free (p);
4028     }
4029 }
4030
4031 static void
4032 test_lookup (void)
4033 {
4034   const gchar *str;
4035   GVariant *dict;
4036   gboolean ok;
4037   gint num;
4038
4039   dict = g_variant_parse (NULL,
4040                           "{'a': <5>, 'b': <'c'>}",
4041                           NULL, NULL, NULL);
4042
4043   ok = g_variant_lookup (dict, "a", "i", &num);
4044   g_assert (ok);
4045   g_assert_cmpint (num, ==, 5);
4046
4047   ok = g_variant_lookup (dict, "a", "&s", &str);
4048   g_assert (!ok);
4049
4050   ok = g_variant_lookup (dict, "q", "&s", &str);
4051   g_assert (!ok);
4052
4053   ok = g_variant_lookup (dict, "b", "i", &num);
4054   g_assert (!ok);
4055
4056   ok = g_variant_lookup (dict, "b", "&s", &str);
4057   g_assert (ok);
4058   g_assert_cmpstr (str, ==, "c");
4059
4060   ok = g_variant_lookup (dict, "q", "&s", &str);
4061   g_assert (!ok);
4062
4063   g_variant_unref (dict);
4064 }
4065
4066 static void
4067 test_compare (void)
4068 {
4069   GVariant *a;
4070   GVariant *b;
4071
4072   a = g_variant_new_byte (5);
4073   b = g_variant_new_byte (6);
4074   g_assert (g_variant_compare (a, b) < 0);
4075   g_variant_unref (a);
4076   g_variant_unref (b);
4077   a = g_variant_new_string ("abc");
4078   b = g_variant_new_string ("abd");
4079   g_assert (g_variant_compare (a, b) < 0);
4080   g_variant_unref (a);
4081   g_variant_unref (b);
4082   a = g_variant_new_boolean (FALSE);
4083   b = g_variant_new_boolean (TRUE);
4084   g_assert (g_variant_compare (a, b) < 0);
4085   g_variant_unref (a);
4086   g_variant_unref (b);
4087 }
4088
4089 static void
4090 test_fixed_array (void)
4091 {
4092   GVariant *a;
4093   gint32 values[5];
4094   const gint32 *elts;
4095   gsize n_elts;
4096   gint i;
4097
4098   n_elts = 0;
4099   a = g_variant_new_parsed ("[1,2,3,4,5]");
4100   elts = g_variant_get_fixed_array (a, &n_elts, sizeof (gint32));
4101   g_assert (n_elts == 5);
4102   for (i = 0; i < 5; i++)
4103     g_assert_cmpint (elts[i], ==, i + 1);
4104   g_variant_unref (a);
4105
4106   n_elts = 0;
4107   for (i = 0; i < 5; i++)
4108     values[i] = i + 1;
4109   a = g_variant_new_fixed_array (G_VARIANT_TYPE_INT32, values,
4110                                  G_N_ELEMENTS (values), sizeof (values[0]));
4111   g_assert_cmpstr (g_variant_get_type_string (a), ==, "ai");
4112   elts = g_variant_get_fixed_array (a, &n_elts, sizeof (gint32));
4113   g_assert (n_elts == 5);
4114   for (i = 0; i < 5; i++)
4115     g_assert_cmpint (elts[i], ==, i + 1);
4116   g_variant_unref (a);
4117 }
4118
4119 int
4120 main (int argc, char **argv)
4121 {
4122   gint i;
4123
4124   g_test_init (&argc, &argv, NULL);
4125
4126   g_test_add_func ("/gvariant/type", test_gvarianttype);
4127   g_test_add_func ("/gvariant/typeinfo", test_gvarianttypeinfo);
4128   g_test_add_func ("/gvariant/serialiser/maybe", test_maybes);
4129   g_test_add_func ("/gvariant/serialiser/array", test_arrays);
4130   g_test_add_func ("/gvariant/serialiser/tuple", test_tuples);
4131   g_test_add_func ("/gvariant/serialiser/variant", test_variants);
4132   g_test_add_func ("/gvariant/serialiser/strings", test_strings);
4133   g_test_add_func ("/gvariant/serialiser/byteswap", test_byteswaps);
4134
4135   for (i = 1; i <= 20; i += 4)
4136     {
4137       char *testname;
4138
4139       testname = g_strdup_printf ("/gvariant/serialiser/fuzz/%d%%", i);
4140       g_test_add_data_func (testname, GINT_TO_POINTER (i),
4141                             (gpointer) test_fuzzes);
4142       g_free (testname);
4143     }
4144
4145   g_test_add_func ("/gvariant/utf8", test_utf8);
4146   g_test_add_func ("/gvariant/containers", test_containers);
4147   g_test_add_func ("/gvariant/format-strings", test_format_strings);
4148   g_test_add_func ("/gvariant/invalid-varargs", test_invalid_varargs);
4149   g_test_add_func ("/gvariant/varargs", test_varargs);
4150   g_test_add_func ("/gvariant/valist", test_valist);
4151   g_test_add_func ("/gvariant/builder-memory", test_builder_memory);
4152   g_test_add_func ("/gvariant/hashing", test_hashing);
4153   g_test_add_func ("/gvariant/byteswap", test_gv_byteswap);
4154   g_test_add_func ("/gvariant/parser", test_parses);
4155   g_test_add_func ("/gvariant/parse-failures", test_parse_failures);
4156   g_test_add_func ("/gvariant/parse-positional", test_parse_positional);
4157   g_test_add_func ("/gvariant/floating", test_floating);
4158   g_test_add_func ("/gvariant/bytestring", test_bytestring);
4159   g_test_add_func ("/gvariant/lookup-value", test_lookup_value);
4160   g_test_add_func ("/gvariant/lookup", test_lookup);
4161   g_test_add_func ("/gvariant/compare", test_compare);
4162   g_test_add_func ("/gvariant/fixed-array", test_fixed_array);
4163
4164   return g_test_run ();
4165 }