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