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