Bug 610858 - gvariant test fails sometimes
[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 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_string,   13, "hello world!" },
1770     { is_nval,     13, "hello world\0" },
1771     { is_nval,     13, "hello\0world!" },
1772     { is_nval,     12, "hello world!" },
1773
1774     { is_objpath,   2, "/" },
1775     { is_objpath,   3, "/a" },
1776     { is_string,    3, "//" },
1777     { is_objpath,  11, "/some/path" },
1778     { is_string,   12, "/some/path/" },
1779     { is_nval,     11, "/some\0path" },
1780     { is_string,   11, "/some\\path" },
1781     { is_string,   12, "/some//path" },
1782     { is_string,   12, "/some-/path" },
1783
1784     { is_sig,       2, "i" },
1785     { is_sig,       2, "s" },
1786     { is_sig,       5, "(si)" },
1787     { is_string,    4, "(si" },
1788     { is_string,    2, "*" },
1789     { is_sig,       3, "ai" },
1790     { is_string,    3, "mi" },
1791     { is_string,    2, "r" },
1792     { is_sig,      15, "(yyy{sv}ssiai)" },
1793     { is_string,   16, "(yyy{yv}ssiai))" },
1794     { is_string,   15, "(yyy{vv}ssiai)" },
1795     { is_string,   15, "(yyy{sv)ssiai}" }
1796   };
1797   guint i;
1798
1799   for (i = 0; i < G_N_ELEMENTS (test_cases); i++)
1800     {
1801       guint flags;
1802
1803       flags = g_variant_serialiser_is_string (test_cases[i].data,
1804                                               test_cases[i].size)
1805         ? 1 : 0;
1806
1807       flags |= g_variant_serialiser_is_object_path (test_cases[i].data,
1808                                                     test_cases[i].size)
1809         ? 2 : 0;
1810
1811       flags |= g_variant_serialiser_is_signature (test_cases[i].data,
1812                                                   test_cases[i].size)
1813         ? 4 : 0;
1814
1815       g_assert (flags == test_cases[i].flags);
1816     }
1817 }
1818
1819 typedef struct _TreeInstance TreeInstance;
1820 struct _TreeInstance
1821 {
1822   GVariantTypeInfo *info;
1823
1824   TreeInstance **children;
1825   gsize n_children;
1826
1827   union {
1828     guint64 integer;
1829     gdouble floating;
1830     gchar string[32];
1831   } data;
1832   gsize data_size;
1833 };
1834
1835 static GVariantType *
1836 make_random_definite_type (int depth)
1837 {
1838   GString *description;
1839   GString *type_string;
1840   GVariantType *type;
1841
1842   description = g_string_new (NULL);
1843   type_string = g_string_new (NULL);
1844   type = append_type_string (type_string, description, TRUE, depth);
1845   g_string_free (description, TRUE);
1846   g_string_free (type_string, TRUE);
1847
1848   return type;
1849 }
1850
1851 static void
1852 make_random_string (gchar              *string,
1853                     gsize               size,
1854                     const GVariantType *type)
1855 {
1856   gint i;
1857
1858   /* create strings that are valid signature strings */
1859 #define good_chars "bynqiuxthdsog"
1860
1861   for (i = 0; i < size - 1; i++)
1862     string[i] = good_chars[g_test_rand_int_range (0, strlen (good_chars))];
1863   string[i] = '\0';
1864
1865   /* in case we need an object path, prefix a '/' */
1866   if (*g_variant_type_peek_string (type) == 'o')
1867     string[0] = '/';
1868
1869 #undef good_chars
1870 }
1871
1872 static TreeInstance *
1873 tree_instance_new (const GVariantType *type,
1874                    int                 depth)
1875 {
1876   const GVariantType *child_type = NULL;
1877   GVariantType *mytype = NULL;
1878   TreeInstance *instance;
1879   gboolean is_tuple_type;
1880
1881   if (type == NULL)
1882     type = mytype = make_random_definite_type (depth);
1883
1884   instance = g_slice_new (TreeInstance);
1885   instance->info = g_variant_type_info_get (type);
1886   instance->children = NULL;
1887   instance->n_children = 0;
1888   instance->data_size = 0;
1889
1890   is_tuple_type = FALSE;
1891
1892   switch (*g_variant_type_peek_string (type))
1893     {
1894     case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
1895       instance->n_children = g_test_rand_int_range (0, 2);
1896       child_type = g_variant_type_element (type);
1897       break;
1898
1899     case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
1900       instance->n_children = g_test_rand_int_range (0, MAX_ARRAY_CHILDREN);
1901       child_type = g_variant_type_element (type);
1902       break;
1903
1904     case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
1905     case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
1906       instance->n_children = g_variant_type_n_items (type);
1907       child_type = g_variant_type_first (type);
1908       is_tuple_type = TRUE;
1909       break;
1910
1911     case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
1912       instance->n_children = 1;
1913       child_type = NULL;
1914       break;
1915
1916     case 'b':
1917       instance->data.integer = g_test_rand_int_range (0, 2);
1918       instance->data_size = 1;
1919       break;
1920
1921     case 'y':
1922       instance->data.integer = g_test_rand_int ();
1923       instance->data_size = 1;
1924       break;
1925
1926     case 'n': case 'q':
1927       instance->data.integer = g_test_rand_int ();
1928       instance->data_size = 2;
1929       break;
1930
1931     case 'i': case 'u': case 'h':
1932       instance->data.integer = g_test_rand_int ();
1933       instance->data_size = 4;
1934       break;
1935
1936     case 'x': case 't':
1937       instance->data.integer = g_test_rand_int ();
1938       instance->data.integer <<= 32;
1939       instance->data.integer |= (guint32) g_test_rand_int ();
1940       instance->data_size = 8;
1941       break;
1942
1943     case 'd':
1944       instance->data.floating = g_test_rand_double ();
1945       instance->data_size = 8;
1946       break;
1947
1948     case 's': case 'o': case 'g':
1949       instance->data_size = g_test_rand_int_range (10, 20);
1950       make_random_string (instance->data.string, instance->data_size, type);
1951       break;
1952     }
1953
1954   if (instance->data_size == 0)
1955     /* no data -> it is a container */
1956     {
1957       guint i;
1958
1959       instance->children = g_new (TreeInstance *, instance->n_children);
1960
1961       for (i = 0; i < instance->n_children; i++)
1962         {
1963           instance->children[i] = tree_instance_new (child_type, depth - 1);
1964
1965           if (is_tuple_type)
1966             child_type = g_variant_type_next (child_type);
1967         }
1968
1969       g_assert (!is_tuple_type || child_type == NULL);
1970     }
1971
1972   g_variant_type_free (mytype);
1973
1974   return instance;
1975 }
1976
1977 static void
1978 tree_instance_free (TreeInstance *instance)
1979 {
1980   gint i;
1981
1982   g_variant_type_info_unref (instance->info);
1983   for (i = 0; i < instance->n_children; i++)
1984     tree_instance_free (instance->children[i]);
1985   g_free (instance->children);
1986   g_slice_free (TreeInstance, instance);
1987 }
1988
1989 static gboolean i_am_writing_byteswapped;
1990
1991 static void
1992 tree_filler (GVariantSerialised *serialised,
1993              gpointer            data)
1994 {
1995   TreeInstance *instance = data;
1996
1997   if (serialised->type_info == NULL)
1998     serialised->type_info = instance->info;
1999
2000   if (instance->data_size == 0)
2001     /* is a container */
2002     {
2003       if (serialised->size == 0)
2004         serialised->size =
2005           g_variant_serialiser_needed_size (instance->info, tree_filler,
2006                                             (gpointer *) instance->children,
2007                                             instance->n_children);
2008
2009       if (serialised->data)
2010         g_variant_serialiser_serialise (*serialised, tree_filler,
2011                                         (gpointer *) instance->children,
2012                                         instance->n_children);
2013     }
2014   else
2015     /* it is a leaf */
2016     {
2017       if (serialised->size == 0)
2018         serialised->size = instance->data_size;
2019
2020       if (serialised->data)
2021         {
2022           switch (instance->data_size)
2023             {
2024             case 1:
2025               *serialised->data = instance->data.integer;
2026               break;
2027
2028             case 2:
2029               {
2030                 guint16 value = instance->data.integer;
2031
2032                 if (i_am_writing_byteswapped)
2033                   value = GUINT16_SWAP_LE_BE (value);
2034
2035                 *(guint16 *) serialised->data = value;
2036               }
2037               break;
2038
2039             case 4:
2040               {
2041                 guint32 value = instance->data.integer;
2042
2043                 if (i_am_writing_byteswapped)
2044                   value = GUINT32_SWAP_LE_BE (value);
2045
2046                 *(guint32 *) serialised->data = value;
2047               }
2048               break;
2049
2050             case 8:
2051               {
2052                 guint64 value = instance->data.integer;
2053
2054                 if (i_am_writing_byteswapped)
2055                   value = GUINT64_SWAP_LE_BE (value);
2056
2057                 *(guint64 *) serialised->data = value;
2058               }
2059               break;
2060
2061             default:
2062               memcpy (serialised->data,
2063                       instance->data.string,
2064                       instance->data_size);
2065               break;
2066             }
2067         }
2068     }
2069 }
2070
2071 static gboolean
2072 check_tree (TreeInstance       *instance,
2073             GVariantSerialised  serialised)
2074 {
2075   if (instance->info != serialised.type_info)
2076     return FALSE;
2077
2078   if (instance->data_size == 0)
2079     /* is a container */
2080     {
2081       gint i;
2082
2083       if (g_variant_serialised_n_children (serialised) !=
2084           instance->n_children)
2085         return FALSE;
2086
2087       for (i = 0; i < instance->n_children; i++)
2088         {
2089           GVariantSerialised child;
2090           gpointer data = NULL;
2091           gboolean ok;
2092
2093           child = g_variant_serialised_get_child (serialised, i);
2094           if (child.size && child.data == NULL)
2095             child.data = data = g_malloc0 (child.size);
2096           ok = check_tree (instance->children[i], child);
2097           g_variant_type_info_unref (child.type_info);
2098           g_free (data);
2099
2100           if (!ok)
2101             return FALSE;
2102         }
2103
2104       return TRUE;
2105     }
2106   else
2107     /* it is a leaf */
2108     {
2109       switch (instance->data_size)
2110         {
2111         case 1:
2112           g_assert (serialised.size == 1);
2113           return *(guint8 *) serialised.data ==
2114                   (guint8) instance->data.integer;
2115
2116         case 2:
2117           g_assert (serialised.size == 2);
2118           return *(guint16 *) serialised.data ==
2119                   (guint16) instance->data.integer;
2120
2121         case 4:
2122           g_assert (serialised.size == 4);
2123           return *(guint32 *) serialised.data ==
2124                   (guint32) instance->data.integer;
2125
2126         case 8:
2127           g_assert (serialised.size == 8);
2128           return *(guint64 *) serialised.data ==
2129                   (guint64) instance->data.integer;
2130
2131         default:
2132           if (serialised.size != instance->data_size)
2133             return FALSE;
2134
2135           return memcmp (serialised.data,
2136                          instance->data.string,
2137                          instance->data_size) == 0;
2138         }
2139     }
2140 }
2141
2142 static void
2143 serialise_tree (TreeInstance       *tree,
2144                 GVariantSerialised *serialised)
2145 {
2146   GVariantSerialised empty = {  };
2147
2148   *serialised = empty;
2149   tree_filler (serialised, tree);
2150   serialised->data = g_malloc (serialised->size);
2151   tree_filler (serialised, tree);
2152 }
2153
2154 static void
2155 test_byteswap (void)
2156 {
2157   GVariantSerialised one, two;
2158   TreeInstance *tree;
2159
2160   tree = tree_instance_new (NULL, 3);
2161   serialise_tree (tree, &one);
2162
2163   i_am_writing_byteswapped = TRUE;
2164   serialise_tree (tree, &two);
2165   i_am_writing_byteswapped = FALSE;
2166
2167   g_variant_serialised_byteswap (two);
2168
2169   g_assert_cmpint (one.size, ==, two.size);
2170   g_assert (memcmp (one.data, two.data, one.size) == 0);
2171
2172   tree_instance_free (tree);
2173   g_free (one.data);
2174   g_free (two.data);
2175 }
2176
2177 static void
2178 test_byteswaps (void)
2179 {
2180   int i;
2181
2182   for (i = 0; i < 200; i++)
2183     test_byteswap ();
2184
2185   g_variant_type_info_assert_no_infos ();
2186 }
2187
2188 static void
2189 test_fuzz (gdouble *fuzziness)
2190 {
2191   GVariantSerialised serialised;
2192   TreeInstance *tree;
2193
2194   /* make an instance */
2195   tree = tree_instance_new (NULL, 3);
2196
2197   /* serialise it */
2198   serialise_tree (tree, &serialised);
2199
2200   g_assert (g_variant_serialised_is_normal (serialised));
2201   g_assert (check_tree (tree, serialised));
2202
2203   if (serialised.size)
2204     {
2205       gboolean fuzzed = FALSE;
2206       gboolean a, b;
2207
2208       while (!fuzzed)
2209         {
2210           gint i;
2211
2212           for (i = 0; i < serialised.size; i++)
2213             if (randomly (*fuzziness))
2214               {
2215                 serialised.data[i] += g_test_rand_int_range (1, 256);
2216                 fuzzed = TRUE;
2217               }
2218         }
2219
2220       /* at least one byte in the serialised data has changed.
2221        *
2222        * this means that at least one of the following is true:
2223        *
2224        *    - the serialised data now represents a different value:
2225        *        check_tree() will return FALSE
2226        *
2227        *    - the serialised data is in non-normal form:
2228        *        g_variant_serialiser_is_normal() will return FALSE
2229        *
2230        * we always do both checks to increase exposure of the serialiser
2231        * to corrupt data.
2232        */
2233       a = g_variant_serialised_is_normal (serialised);
2234       b = check_tree (tree, serialised);
2235
2236       g_assert (!a || !b);
2237     }
2238
2239   tree_instance_free (tree);
2240   g_free (serialised.data);
2241 }
2242
2243
2244 static void
2245 test_fuzzes (gpointer data)
2246 {
2247   gdouble fuzziness;
2248   int i;
2249
2250   fuzziness = GPOINTER_TO_INT (data) / 100.;
2251
2252   for (i = 0; i < 200; i++)
2253     test_fuzz (&fuzziness);
2254
2255   g_variant_type_info_assert_no_infos ();
2256 }
2257
2258 static GVariant *
2259 tree_instance_get_gvariant (TreeInstance *tree)
2260 {
2261   const GVariantType *type;
2262   GVariant *result;
2263
2264   type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
2265
2266   switch (g_variant_type_info_get_type_char (tree->info))
2267     {
2268     case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
2269       {
2270         const GVariantType *child_type;
2271         GVariant *child;
2272
2273         if (tree->n_children)
2274           child = tree_instance_get_gvariant (tree->children[0]);
2275         else
2276           child = NULL;
2277
2278         child_type = g_variant_type_element (type);
2279
2280         if (child != NULL && randomly (0.5))
2281           child_type = NULL;
2282
2283         result = g_variant_new_maybe (child_type, child);
2284       }
2285       break;
2286
2287     case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
2288       {
2289         const GVariantType *child_type;
2290         GVariant **children;
2291         gint i;
2292
2293         children = g_new (GVariant *, tree->n_children);
2294         for (i = 0; i < tree->n_children; i++)
2295           children[i] = tree_instance_get_gvariant (tree->children[i]);
2296
2297         child_type = g_variant_type_element (type);
2298
2299         if (i > 0 && randomly (0.5))
2300           child_type = NULL;
2301
2302         result = g_variant_new_array (child_type, children, tree->n_children);
2303         g_free (children);
2304       }
2305       break;
2306
2307     case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
2308       {
2309         GVariant **children;
2310         gint i;
2311
2312         children = g_new (GVariant *, tree->n_children);
2313         for (i = 0; i < tree->n_children; i++)
2314           children[i] = tree_instance_get_gvariant (tree->children[i]);
2315
2316         result = g_variant_new_tuple (children, tree->n_children);
2317         g_free (children);
2318       }
2319       break;
2320
2321     case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
2322       {
2323         GVariant *key, *val;
2324
2325         g_assert (tree->n_children == 2);
2326
2327         key = tree_instance_get_gvariant (tree->children[0]);
2328         val = tree_instance_get_gvariant (tree->children[1]);
2329
2330         result = g_variant_new_dict_entry (key, val);
2331       }
2332       break;
2333
2334     case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
2335       {
2336         GVariant *value;
2337
2338         g_assert (tree->n_children == 1);
2339
2340         value = tree_instance_get_gvariant (tree->children[0]);
2341         result = g_variant_new_variant (value);
2342       }
2343       break;
2344
2345     case 'b':
2346       result = g_variant_new_boolean (tree->data.integer > 0);
2347       break;
2348
2349     case 'y':
2350       result = g_variant_new_byte (tree->data.integer);
2351       break;
2352
2353     case 'n':
2354       result = g_variant_new_int16 (tree->data.integer);
2355       break;
2356
2357     case 'q':
2358       result = g_variant_new_uint16 (tree->data.integer);
2359       break;
2360
2361     case 'i':
2362       result = g_variant_new_int32 (tree->data.integer);
2363       break;
2364
2365     case 'u':
2366       result = g_variant_new_uint32 (tree->data.integer);
2367       break;
2368
2369     case 'x':
2370       result = g_variant_new_int64 (tree->data.integer);
2371       break;
2372
2373     case 't':
2374       result = g_variant_new_uint64 (tree->data.integer);
2375       break;
2376
2377     case 'h':
2378       result = g_variant_new_handle (tree->data.integer);
2379       break;
2380
2381     case 'd':
2382       result = g_variant_new_double (tree->data.floating);
2383       break;
2384
2385     case 's':
2386       result = g_variant_new_string (tree->data.string);
2387       break;
2388
2389     case 'o':
2390       result = g_variant_new_object_path (tree->data.string);
2391       break;
2392
2393     case 'g':
2394       result = g_variant_new_signature (tree->data.string);
2395       break;
2396
2397     default:
2398       g_assert_not_reached ();
2399     }
2400
2401   return result;
2402 }
2403
2404 static gboolean
2405 tree_instance_check_gvariant (TreeInstance *tree,
2406                               GVariant     *value)
2407 {
2408   const GVariantType *type;
2409
2410   type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
2411   g_assert (g_variant_is_of_type (value, type));
2412
2413   switch (g_variant_type_info_get_type_char (tree->info))
2414     {
2415     case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
2416       {
2417         GVariant *child;
2418         gboolean equal;
2419
2420         child = g_variant_get_maybe (value);
2421
2422         if (child != NULL && tree->n_children == 1)
2423           equal = tree_instance_check_gvariant (tree->children[0], child);
2424         else if (child == NULL && tree->n_children == 0)
2425           equal = TRUE;
2426         else
2427           equal = FALSE;
2428
2429         if (child != NULL)
2430           g_variant_unref (child);
2431
2432         return equal;
2433       }
2434       break;
2435
2436     case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
2437     case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
2438     case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
2439       {
2440         gsize i;
2441
2442         if (g_variant_n_children (value) != tree->n_children)
2443           return FALSE;
2444
2445         for (i = 0; i < tree->n_children; i++)
2446           {
2447             GVariant *child;
2448             gboolean equal;
2449
2450             child = g_variant_get_child_value (value, i);
2451             equal = tree_instance_check_gvariant (tree->children[i], child);
2452             g_variant_unref (child);
2453
2454             if (!equal)
2455               return FALSE;
2456           }
2457
2458         return TRUE;
2459       }
2460       break;
2461
2462     case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
2463       {
2464         const gchar *str1, *str2;
2465         GVariant *child;
2466         gboolean equal;
2467
2468         child = g_variant_get_variant (value);
2469         str1 = g_variant_get_type_string (child);
2470         str2 = g_variant_type_info_get_type_string (tree->children[0]->info);
2471         /* GVariant only keeps one copy of type strings around */
2472         equal = str1 == str2 &&
2473                 tree_instance_check_gvariant (tree->children[0], child);
2474
2475         g_variant_unref (child);
2476
2477         return equal;
2478       }
2479       break;
2480
2481     case 'b':
2482       return g_variant_get_boolean (value) == tree->data.integer;
2483
2484     case 'y':
2485       return g_variant_get_byte (value) == (guchar) tree->data.integer;
2486
2487     case 'n':
2488       return g_variant_get_int16 (value) == (gint16) tree->data.integer;
2489
2490     case 'q':
2491       return g_variant_get_uint16 (value) == (guint16) tree->data.integer;
2492
2493     case 'i':
2494       return g_variant_get_int32 (value) == (gint32) tree->data.integer;
2495
2496     case 'u':
2497       return g_variant_get_uint32 (value) == (guint32) tree->data.integer;
2498
2499     case 'x':
2500       return g_variant_get_int64 (value) == (gint64) tree->data.integer;
2501
2502     case 't':
2503       return g_variant_get_uint64 (value) == (guint64) tree->data.integer;
2504
2505     case 'h':
2506       return g_variant_get_handle (value) == (gint32) tree->data.integer;
2507
2508     case 'd':
2509       {
2510         gdouble floating = g_variant_get_double (value);
2511
2512         return memcmp (&floating, &tree->data.floating, sizeof floating) == 0;
2513       }
2514
2515     case 's':
2516     case 'o':
2517     case 'g':
2518       return strcmp (g_variant_get_string (value, NULL),
2519                      tree->data.string) == 0;
2520
2521     default:
2522       g_assert_not_reached ();
2523     }
2524 }
2525
2526 static void
2527 tree_instance_build_gvariant (TreeInstance    *tree,
2528                               GVariantBuilder *builder,
2529                               gboolean         guess_ok)
2530 {
2531   const GVariantType *type;
2532
2533   type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
2534
2535   if (g_variant_type_is_container (type))
2536     {
2537       gsize i;
2538
2539       /* force GVariantBuilder to guess the type half the time */
2540       if (guess_ok && randomly (0.5))
2541         {
2542           if (g_variant_type_is_array (type) && tree->n_children)
2543             type = G_VARIANT_TYPE_ARRAY;
2544
2545           if (g_variant_type_is_maybe (type) && tree->n_children)
2546             type = G_VARIANT_TYPE_MAYBE;
2547
2548           if (g_variant_type_is_tuple (type))
2549             type = G_VARIANT_TYPE_TUPLE;
2550
2551           if (g_variant_type_is_dict_entry (type))
2552             type = G_VARIANT_TYPE_DICT_ENTRY;
2553         }
2554       else
2555         guess_ok = FALSE;
2556
2557       g_variant_builder_open (builder, type);
2558
2559       for (i = 0; i < tree->n_children; i++)
2560         tree_instance_build_gvariant (tree->children[i], builder, guess_ok);
2561
2562       g_variant_builder_close (builder);
2563     }
2564   else
2565     g_variant_builder_add_value (builder, tree_instance_get_gvariant (tree));
2566 }
2567
2568
2569 static gboolean
2570 tree_instance_check_iter (TreeInstance *tree,
2571                           GVariantIter *iter)
2572 {
2573   GVariant *value;
2574
2575   value = g_variant_iter_next_value (iter);
2576
2577   if (g_variant_is_container (value))
2578     {
2579       gsize i;
2580
2581       iter = g_variant_iter_new (value);
2582       g_variant_unref (value);
2583
2584       if (g_variant_iter_n_children (iter) != tree->n_children)
2585         {
2586           g_variant_iter_free (iter);
2587           return FALSE;
2588         }
2589
2590       for (i = 0; i < tree->n_children; i++)
2591         if (!tree_instance_check_iter (tree->children[i], iter))
2592           {
2593             g_variant_iter_free (iter);
2594             return FALSE;
2595           }
2596
2597       g_assert (g_variant_iter_next_value (iter) == NULL);
2598       g_variant_iter_free (iter);
2599
2600       return TRUE;
2601     }
2602
2603   else
2604     {
2605       gboolean equal;
2606
2607       equal = tree_instance_check_gvariant (tree, value);
2608       g_variant_unref (value);
2609
2610       return equal;
2611     }
2612 }
2613
2614 static void
2615 test_container (void)
2616 {
2617   TreeInstance *tree;
2618   GVariant *value;
2619   gchar *s1, *s2;
2620
2621   tree = tree_instance_new (NULL, 3);
2622   value = g_variant_ref_sink (tree_instance_get_gvariant (tree));
2623
2624   s1 = g_variant_print (value, TRUE);
2625   g_assert (tree_instance_check_gvariant (tree, value));
2626
2627   g_variant_get_data (value);
2628
2629   s2 = g_variant_print (value, TRUE);
2630   g_assert (tree_instance_check_gvariant (tree, value));
2631
2632   g_assert_cmpstr (s1, ==, s2);
2633
2634   if (g_variant_is_container (value))
2635     {
2636       GVariantBuilder builder;
2637       GVariantIter iter;
2638       GVariant *built;
2639       GVariant *val;
2640       gchar *s3;
2641
2642       g_variant_builder_init (&builder, G_VARIANT_TYPE_VARIANT);
2643       tree_instance_build_gvariant (tree, &builder, TRUE);
2644       built = g_variant_builder_end (&builder);
2645       g_variant_ref_sink (built);
2646       g_variant_get_data (built);
2647       val = g_variant_get_variant (built);
2648
2649       s3 = g_variant_print (val, TRUE);
2650       g_assert_cmpstr (s1, ==, s3);
2651
2652       g_variant_iter_init (&iter, built);
2653       g_assert (tree_instance_check_iter (tree, &iter));
2654       g_assert (g_variant_iter_next_value (&iter) == NULL);
2655
2656       g_variant_unref (built);
2657       g_variant_unref (val);
2658       g_free (s3);
2659     }
2660
2661   tree_instance_free (tree);
2662   g_variant_unref (value);
2663   g_free (s2);
2664   g_free (s1);
2665 }
2666
2667 static void
2668 test_containers (void)
2669 {
2670   gint i;
2671
2672   for (i = 0; i < 100; i++)
2673     {
2674       test_container ();
2675     }
2676
2677   g_variant_type_info_assert_no_infos ();
2678 }
2679
2680 static void
2681 test_format_strings (void)
2682 {
2683   GVariantType *type;
2684   const gchar *end;
2685
2686   g_assert (g_variant_format_string_scan ("i", NULL, &end) && *end == '\0');
2687   g_assert (g_variant_format_string_scan ("@i", NULL, &end) && *end == '\0');
2688   g_assert (g_variant_format_string_scan ("@ii", NULL, &end) && *end == 'i');
2689   g_assert (g_variant_format_string_scan ("^a&s", NULL, &end) && *end == '\0');
2690   g_assert (g_variant_format_string_scan ("(^as)", NULL, &end) &&
2691             *end == '\0');
2692   g_assert (!g_variant_format_string_scan ("(^s)", NULL, &end));
2693   g_assert (!g_variant_format_string_scan ("(^a)", NULL, &end));
2694   g_assert (!g_variant_format_string_scan ("(z)", NULL, &end));
2695   g_assert (!g_variant_format_string_scan ("az", NULL, &end));
2696   g_assert (!g_variant_format_string_scan ("{**}", NULL, &end));
2697   g_assert (!g_variant_format_string_scan ("{@**}", NULL, &end));
2698   g_assert (g_variant_format_string_scan ("{@y*}", NULL, &end) &&
2699             *end == '\0');
2700   g_assert (g_variant_format_string_scan ("{yv}", NULL, &end) &&
2701             *end == '\0');
2702   g_assert (!g_variant_format_string_scan ("{vv}", NULL, &end));
2703   g_assert (!g_variant_format_string_scan ("{y}", NULL, &end));
2704   g_assert (!g_variant_format_string_scan ("{yyy}", NULL, &end));
2705   g_assert (!g_variant_format_string_scan ("{ya}", NULL, &end));
2706   g_assert (g_variant_format_string_scan ("&s", NULL, &end) && *end == '\0');
2707   g_assert (!g_variant_format_string_scan ("&as", NULL, &end));
2708   g_assert (!g_variant_format_string_scan ("@z", NULL, &end));
2709   g_assert (!g_variant_format_string_scan ("az", NULL, &end));
2710   g_assert (!g_variant_format_string_scan ("a&s", NULL, &end));
2711
2712   type = g_variant_format_string_scan_type ("mm(@xy^a&s*?@?)", NULL, &end);
2713   g_assert (type && *end == '\0');
2714   g_assert (g_variant_type_equal (type, G_VARIANT_TYPE ("mm(xyas*?\?)")));
2715   g_variant_type_free (type);
2716
2717   type = g_variant_format_string_scan_type ("mm(@xy^a&*?@?)", NULL, NULL);
2718   g_assert (type == NULL);
2719 }
2720
2721 static void
2722 exit_on_abort (int signal)
2723 {
2724   exit (signal);
2725 }
2726
2727 static gboolean
2728 do_failed_test (const gchar *pattern)
2729 {
2730   if (g_test_trap_fork (1000000, G_TEST_TRAP_SILENCE_STDERR))
2731     {
2732       signal (SIGABRT, exit_on_abort);
2733       return TRUE;
2734     }
2735
2736   g_test_trap_assert_failed ();
2737   g_test_trap_assert_stderr (pattern);
2738
2739   return FALSE;
2740 }
2741
2742 static void
2743 test_invalid_varargs (void)
2744 {
2745   if (do_failed_test ("*not a valid GVariant format string*"))
2746     {
2747       g_variant_new ("z");
2748       abort ();
2749     }
2750
2751   if (do_failed_test ("*valid GVariant format string as a prefix*"))
2752     {
2753       const gchar *end;
2754
2755       g_variant_new_va ("z", &end, NULL);
2756       abort ();
2757     }
2758
2759   if (do_failed_test ("*type of `q' but * has a type of `y'*"))
2760     {
2761       g_variant_get (g_variant_new ("y", 'a'), "q");
2762       abort ();
2763     }
2764 }
2765
2766 static void
2767 check_and_free (GVariant    *value,
2768                 const gchar *str)
2769 {
2770   gchar *valstr = g_variant_print (value, FALSE);
2771   g_assert_cmpstr (str, ==, valstr);
2772   g_variant_unref (value);
2773   g_free (valstr);
2774 }
2775
2776 static void
2777 test_varargs (void)
2778 {
2779   {
2780     GVariantBuilder array;
2781
2782     g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
2783     g_variant_builder_add (&array, "{sv}", "size",
2784                            g_variant_new ("(ii)", 800, 600));
2785     g_variant_builder_add (&array, "{sv}", "title",
2786                            g_variant_new_string ("Test case"));
2787     g_variant_builder_add_value (&array,
2788       g_variant_new_dict_entry (g_variant_new_string ("temperature"),
2789                                 g_variant_new_variant (
2790                                   g_variant_new_double (37.5))));
2791     check_and_free (g_variant_new ("(ma{sv}m(a{sv})ma{sv}ii)",
2792                                    NULL, FALSE, NULL, &array, 7777, 8888),
2793                     "(Nothing, Nothing, {'size': <(800, 600)>, "
2794                                         "'title': <'Test case'>, "
2795                                         "'temperature': <37.5>}, "
2796                      "7777, 8888)");
2797
2798     check_and_free (g_variant_new ("(imimimmimmimmi)",
2799                                    123,
2800                                    FALSE, 321,
2801                                    TRUE, 123,
2802                                    FALSE, TRUE, 321,
2803                                    TRUE, FALSE, 321,
2804                                    TRUE, TRUE, 123),
2805                     "(123, Nothing, 123, Nothing, Just Nothing, 123)");
2806
2807     check_and_free (g_variant_new ("(ybnixd)",
2808                                    'a', 1, 22, 33, (guint64) 44, 5.5),
2809                     "(0x61, true, 22, 33, 44, 5.5)");
2810
2811     check_and_free (g_variant_new ("(@y?*rv)",
2812                                    g_variant_new ("y", 'a'),
2813                                    g_variant_new ("y", 'b'),
2814                                    g_variant_new ("y", 'c'),
2815                                    g_variant_new ("(y)", 'd'),
2816                                    g_variant_new ("y", 'e')),
2817                     "(0x61, 0x62, 0x63, (0x64,), <byte 0x65>)");
2818   }
2819
2820   {
2821     GVariantBuilder array;
2822     GVariantIter iter;
2823     GVariant *value;
2824     gchar *number;
2825     gboolean just;
2826     gint i, val;
2827
2828     g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
2829     for (i = 0; i < 100; i++)
2830       {
2831         number = g_strdup_printf ("%d", i);
2832         g_variant_builder_add (&array, "s", number);
2833         g_free (number);
2834       }
2835
2836     value = g_variant_builder_end (&array);
2837     g_variant_iter_init (&iter, value);
2838
2839     i = 0;
2840     while (g_variant_iter_loop (&iter, "s", &number))
2841       {
2842         gchar *check = g_strdup_printf ("%d", i++);
2843         g_assert_cmpstr (number, ==, check);
2844         g_free (check);
2845       }
2846     g_assert (number == NULL);
2847     g_assert (i == 100);
2848
2849     g_variant_unref (value);
2850
2851     g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
2852     for (i = 0; i < 100; i++)
2853       g_variant_builder_add (&array, "mi", i % 2 == 0, i);
2854     value = g_variant_builder_end (&array);
2855
2856     i = 0;
2857     g_variant_iter_init (&iter, value);
2858     while (g_variant_iter_loop (&iter, "mi", NULL, &val))
2859       g_assert (val == i++ || val == 0);
2860     g_assert (i == 100);
2861
2862     i = 0;
2863     g_variant_iter_init (&iter, value);
2864     while (g_variant_iter_loop (&iter, "mi", &just, &val))
2865       {
2866         gint this = i++;
2867
2868         if (this % 2 == 0)
2869           {
2870             g_assert (just);
2871             g_assert (val == this);
2872           }
2873         else
2874           {
2875             g_assert (!just);
2876             g_assert (val == 0);
2877           }
2878       }
2879     g_assert (i == 100);
2880
2881     g_variant_unref (value);
2882   }
2883
2884   {
2885     const gchar *strvector[] = {"/hello", "/world", NULL};
2886     const gchar *test_strs[] = {"/foo", "/bar", "/baz" };
2887     GVariantBuilder builder;
2888     GVariantIter *array;
2889     GVariantIter tuple;
2890     const gchar **strv;
2891     gchar **my_strv;
2892     GVariant *value;
2893     gchar *str;
2894     gint i;
2895
2896     g_variant_builder_init (&builder, G_VARIANT_TYPE ("ao"));
2897     g_variant_builder_add (&builder, "o", "/foo");
2898     g_variant_builder_add (&builder, "o", "/bar");
2899     g_variant_builder_add (&builder, "o", "/baz");
2900     value = g_variant_new("(ao^ao^a&o)", &builder, strvector, strvector);
2901     g_variant_iter_init (&tuple, value);
2902     g_variant_iter_next (&tuple, "ao", &array);
2903
2904     i = 0;
2905     while (g_variant_iter_loop (array, "o", &str))
2906       g_assert_cmpstr (str, ==, test_strs[i++]);
2907     g_assert (i == 3);
2908
2909     g_variant_iter_free (array);
2910
2911     /* start over */
2912     g_variant_iter_init (&tuple, value);
2913     g_variant_iter_next (&tuple, "ao", &array);
2914
2915     i = 0;
2916     while (g_variant_iter_loop (array, "&o", &str))
2917       g_assert_cmpstr (str, ==, test_strs[i++]);
2918     g_assert (i == 3);
2919
2920     g_variant_iter_free (array);
2921
2922     g_variant_iter_next (&tuple, "^a&o", &strv);
2923     g_variant_iter_next (&tuple, "^ao", &my_strv);
2924
2925     g_assert_cmpstr (strv[0], ==, "/hello");
2926     g_assert_cmpstr (strv[1], ==, "/world");
2927     g_assert (strv[2] == NULL);
2928     g_assert_cmpstr (my_strv[0], ==, "/hello");
2929     g_assert_cmpstr (my_strv[1], ==, "/world");
2930     g_assert (my_strv[2] == NULL);
2931
2932     g_variant_unref (value);
2933     g_strfreev (my_strv);
2934     g_free (strv);
2935   }
2936
2937   {
2938     const gchar *strvector[] = { "i", "ii", "iii", "iv", "v", "vi", NULL };
2939     GVariantBuilder builder;
2940     GVariantIter iter;
2941     GVariantIter *i2;
2942     GVariantIter *i3;
2943     GVariant *value;
2944     GVariant *sub;
2945     gchar **strv;
2946     gint i;
2947
2948     g_variant_builder_init (&builder, G_VARIANT_TYPE ("aag"));
2949     g_variant_builder_open (&builder, G_VARIANT_TYPE ("ag"));
2950     for (i = 0; i < 6; i++)
2951       if (i & 1)
2952         g_variant_builder_add (&builder, "g", strvector[i]);
2953       else
2954         g_variant_builder_add (&builder, "&g", strvector[i]);
2955     g_variant_builder_close (&builder);
2956     g_variant_builder_add (&builder, "^ag", strvector);
2957     g_variant_builder_add (&builder, "^ag", strvector);
2958     value = g_variant_new ("aag", &builder);
2959
2960     g_variant_iter_init (&iter, value);
2961     while (g_variant_iter_loop (&iter, "^ag", &strv))
2962       for (i = 0; i < 6; i++)
2963         g_assert_cmpstr (strv[i], ==, strvector[i]);
2964
2965     g_variant_iter_init (&iter, value);
2966     while (g_variant_iter_loop (&iter, "^a&g", &strv))
2967       for (i = 0; i < 6; i++)
2968         g_assert_cmpstr (strv[i], ==, strvector[i]);
2969
2970     g_variant_iter_init (&iter, value);
2971     while (g_variant_iter_loop (&iter, "ag", &i2))
2972       {
2973         gchar *str;
2974
2975         i = 0;
2976         while (g_variant_iter_loop (i2, "g", &str))
2977           g_assert_cmpstr (str, ==, strvector[i++]);
2978         g_assert (i == 6);
2979       }
2980
2981     g_variant_iter_init (&iter, value);
2982     i3 = g_variant_iter_copy (&iter);
2983     while (g_variant_iter_loop (&iter, "@ag", &sub))
2984       {
2985         gchar *str = g_variant_print (sub, TRUE);
2986         g_assert_cmpstr (str, ==,
2987                          "[signature 'i', 'ii', 'iii', 'iv', 'v', 'vi']");
2988         g_free (str);
2989       }
2990
2991   if (do_failed_test ("*NULL has already been returned*"))
2992     {
2993       g_variant_iter_next_value (&iter);
2994       abort ();
2995     }
2996
2997
2998     while (g_variant_iter_loop (i3, "*", &sub))
2999       {
3000         gchar *str = g_variant_print (sub, TRUE);
3001         g_assert_cmpstr (str, ==,
3002                          "[signature 'i', 'ii', 'iii', 'iv', 'v', 'vi']");
3003         g_free (str);
3004       }
3005
3006     g_variant_iter_free (i3);
3007
3008     for (i = 0; i < g_variant_n_children (value); i++)
3009       {
3010         gint j;
3011
3012         g_variant_get_child (value, i, "*", &sub);
3013
3014         for (j = 0; j < g_variant_n_children (sub); j++)
3015           {
3016             const gchar *str = NULL;
3017             GVariant *cval;
3018
3019             g_variant_get_child (sub, j, "&g", &str);
3020             g_assert_cmpstr (str, ==, strvector[j]);
3021
3022             cval = g_variant_get_child_value (sub, j);
3023             g_variant_get (cval, "&g", &str);
3024             g_assert_cmpstr (str, ==, strvector[j]);
3025             g_variant_unref (cval);
3026           }
3027
3028         g_variant_unref (sub);
3029       }
3030
3031     g_variant_unref (value);
3032   }
3033
3034   {
3035     gboolean justs[10];
3036     GVariant *value;
3037
3038     GVariant *vval;
3039     guchar byteval;
3040     gboolean bval;
3041     gint16 i16val;
3042     guint16 u16val;
3043     gint32 i32val;
3044     guint32 u32val;
3045     gint64 i64val;
3046     guint64 u64val;
3047     gdouble dval;
3048     gint32 hval;
3049
3050     /* test all 'Nothing' */
3051     value = g_variant_new ("(mymbmnmqmimumxmtmhmdmv)",
3052                            FALSE, 'a',
3053                            FALSE, TRUE,
3054                            FALSE, (gint16) 123,
3055                            FALSE, (guint16) 123,
3056                            FALSE, (gint32) 123,
3057                            FALSE, (guint32) 123,
3058                            FALSE, (gint64) 123,
3059                            FALSE, (guint64) 123,
3060                            FALSE, (gint32) -1,
3061                            FALSE, (gdouble) 37.5,
3062                            NULL);
3063
3064     /* both NULL */
3065     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3066                    NULL, NULL,
3067                    NULL, NULL,
3068                    NULL, NULL,
3069                    NULL, NULL,
3070                    NULL, NULL,
3071                    NULL, NULL,
3072                    NULL, NULL,
3073                    NULL, NULL,
3074                    NULL, NULL,
3075                    NULL, NULL,
3076                    NULL);
3077
3078     /* NULL values */
3079     memset (justs, 1, sizeof justs);
3080     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3081                    &justs[0], NULL,
3082                    &justs[1], NULL,
3083                    &justs[2], NULL,
3084                    &justs[3], NULL,
3085                    &justs[4], NULL,
3086                    &justs[5], NULL,
3087                    &justs[6], NULL,
3088                    &justs[7], NULL,
3089                    &justs[8], NULL,
3090                    &justs[9], NULL,
3091                    NULL);
3092     g_assert (!(justs[0] || justs[1] || justs[2] || justs[3] || justs[4] ||
3093                 justs[5] || justs[6] || justs[7] || justs[8] || justs[9]));
3094
3095     /* both non-NULL */
3096     memset (justs, 1, sizeof justs);
3097     byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3098     vval = (void *) 1;
3099     bval = TRUE;
3100     dval = 88.88;
3101     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3102                    &justs[0], &byteval,
3103                    &justs[1], &bval,
3104                    &justs[2], &i16val,
3105                    &justs[3], &u16val,
3106                    &justs[4], &i32val,
3107                    &justs[5], &u32val,
3108                    &justs[6], &i64val,
3109                    &justs[7], &u64val,
3110                    &justs[8], &hval,
3111                    &justs[9], &dval,
3112                    &vval);
3113     g_assert (!(justs[0] || justs[1] || justs[2] || justs[3] || justs[4] ||
3114                 justs[5] || justs[6] || justs[7] || justs[8] || justs[9]));
3115     g_assert (byteval == '\0' && bval == FALSE);
3116     g_assert (i16val == 0 && u16val == 0 && i32val == 0 &&
3117               u32val == 0 && i64val == 0 && u64val == 0 &&
3118               hval == 0 && dval == 0.0);
3119     g_assert (vval == NULL);
3120
3121     /* NULL justs */
3122     byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3123     vval = (void *) 1;
3124     bval = TRUE;
3125     dval = 88.88;
3126     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3127                    NULL, &byteval,
3128                    NULL, &bval,
3129                    NULL, &i16val,
3130                    NULL, &u16val,
3131                    NULL, &i32val,
3132                    NULL, &u32val,
3133                    NULL, &i64val,
3134                    NULL, &u64val,
3135                    NULL, &hval,
3136                    NULL, &dval,
3137                    &vval);
3138     g_assert (byteval == '\0' && bval == FALSE);
3139     g_assert (i16val == 0 && u16val == 0 && i32val == 0 &&
3140               u32val == 0 && i64val == 0 && u64val == 0 &&
3141               hval == 0 && dval == 0.0);
3142     g_assert (vval == NULL);
3143
3144     g_variant_unref (value);
3145
3146
3147     /* test all 'Just' */
3148     value = g_variant_new ("(mymbmnmqmimumxmtmhmdmv)",
3149                            TRUE, 'a',
3150                            TRUE, TRUE,
3151                            TRUE, (gint16) 123,
3152                            TRUE, (guint16) 123,
3153                            TRUE, (gint32) 123,
3154                            TRUE, (guint32) 123,
3155                            TRUE, (gint64) 123,
3156                            TRUE, (guint64) 123,
3157                            TRUE, (gint32) -1,
3158                            TRUE, (gdouble) 37.5,
3159                            g_variant_new ("()"));
3160
3161     /* both NULL */
3162     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3163                    NULL, NULL,
3164                    NULL, NULL,
3165                    NULL, NULL,
3166                    NULL, NULL,
3167                    NULL, NULL,
3168                    NULL, NULL,
3169                    NULL, NULL,
3170                    NULL, NULL,
3171                    NULL, NULL,
3172                    NULL, NULL,
3173                    NULL);
3174
3175     /* NULL values */
3176     memset (justs, 0, sizeof justs);
3177     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3178                    &justs[0], NULL,
3179                    &justs[1], NULL,
3180                    &justs[2], NULL,
3181                    &justs[3], NULL,
3182                    &justs[4], NULL,
3183                    &justs[5], NULL,
3184                    &justs[6], NULL,
3185                    &justs[7], NULL,
3186                    &justs[8], NULL,
3187                    &justs[9], NULL,
3188                    NULL);
3189     g_assert (justs[0] && justs[1] && justs[2] && justs[3] && justs[4] &&
3190               justs[5] && justs[6] && justs[7] && justs[8] && justs[9]);
3191
3192     /* both non-NULL */
3193     memset (justs, 0, sizeof justs);
3194     byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3195     vval = (void *) 1;
3196     bval = FALSE;
3197     dval = 88.88;
3198     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3199                    &justs[0], &byteval,
3200                    &justs[1], &bval,
3201                    &justs[2], &i16val,
3202                    &justs[3], &u16val,
3203                    &justs[4], &i32val,
3204                    &justs[5], &u32val,
3205                    &justs[6], &i64val,
3206                    &justs[7], &u64val,
3207                    &justs[8], &hval,
3208                    &justs[9], &dval,
3209                    &vval);
3210     g_assert (justs[0] && justs[1] && justs[2] && justs[3] && justs[4] &&
3211               justs[5] && justs[6] && justs[7] && justs[8] && justs[9]);
3212     g_assert (byteval == 'a' && bval == TRUE);
3213     g_assert (i16val == 123 && u16val == 123 && i32val == 123 &&
3214               u32val == 123 && i64val == 123 && u64val == 123 &&
3215               hval == -1 && dval == 37.5);
3216     g_assert (g_variant_is_of_type (vval, G_VARIANT_TYPE_UNIT));
3217     g_variant_unref (vval);
3218
3219     /* NULL justs */
3220     byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3221     vval = (void *) 1;
3222     bval = TRUE;
3223     dval = 88.88;
3224     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3225                    NULL, &byteval,
3226                    NULL, &bval,
3227                    NULL, &i16val,
3228                    NULL, &u16val,
3229                    NULL, &i32val,
3230                    NULL, &u32val,
3231                    NULL, &i64val,
3232                    NULL, &u64val,
3233                    NULL, &hval,
3234                    NULL, &dval,
3235                    &vval);
3236     g_assert (byteval == 'a' && bval == TRUE);
3237     g_assert (i16val == 123 && u16val == 123 && i32val == 123 &&
3238               u32val == 123 && i64val == 123 && u64val == 123 &&
3239               hval == -1 && dval == 37.5);
3240     g_assert (g_variant_is_of_type (vval, G_VARIANT_TYPE_UNIT));
3241     g_variant_unref (vval);
3242
3243     g_variant_unref (value);
3244   }
3245
3246   g_variant_type_info_assert_no_infos ();
3247 }
3248
3249 static void
3250 hash_get (GVariant    *value,
3251           const gchar *format,
3252           ...)
3253 {
3254   const gchar *endptr = NULL;
3255   gboolean hash;
3256   va_list ap;
3257
3258   hash = g_str_has_suffix (format, "#");
3259
3260   va_start (ap, format);
3261   g_variant_get_va (value, format, hash ? &endptr : NULL, &ap);
3262   va_end (ap);
3263
3264   if (hash)
3265     g_assert (*endptr == '#');
3266 }
3267
3268 static GVariant *
3269 hash_new (const gchar *format,
3270           ...)
3271 {
3272   const gchar *endptr = NULL;
3273   GVariant *value;
3274   gboolean hash;
3275   va_list ap;
3276
3277   hash = g_str_has_suffix (format, "#");
3278
3279   va_start (ap, format);
3280   value = g_variant_new_va (format, hash ? &endptr : NULL, &ap);
3281   va_end (ap);
3282
3283   if (hash)
3284     g_assert (*endptr == '#');
3285
3286   return value;
3287 }
3288
3289 static void
3290 test_valist (void)
3291 {
3292   GVariant *value;
3293   gint32 x;
3294
3295   x = 0;
3296   value = hash_new ("i", 234);
3297   hash_get (value, "i", &x);
3298   g_assert (x == 234);
3299   g_variant_unref (value);
3300
3301   x = 0;
3302   value = hash_new ("i#", 234);
3303   hash_get (value, "i#", &x);
3304   g_assert (x == 234);
3305   g_variant_unref (value);
3306
3307   g_variant_type_info_assert_no_infos ();
3308 }
3309
3310 static void
3311 test_builder_memory (void)
3312 {
3313   GVariantBuilder *hb;
3314   GVariantBuilder sb;
3315
3316   hb = g_variant_builder_new  (G_VARIANT_TYPE_ARRAY);
3317   g_variant_builder_open (hb, G_VARIANT_TYPE_ARRAY);
3318   g_variant_builder_open (hb, G_VARIANT_TYPE_ARRAY);
3319   g_variant_builder_open (hb, G_VARIANT_TYPE_ARRAY);
3320   g_variant_builder_add (hb, "s", "some value");
3321   g_variant_builder_ref (hb);
3322   g_variant_builder_unref (hb);
3323   g_variant_builder_unref (hb);
3324
3325   hb = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
3326   g_variant_builder_unref (hb);
3327
3328   hb = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
3329   g_variant_builder_clear (hb);
3330   g_variant_builder_unref (hb);
3331
3332   g_variant_builder_init (&sb, G_VARIANT_TYPE_ARRAY);
3333   g_variant_builder_open (&sb, G_VARIANT_TYPE_ARRAY);
3334   g_variant_builder_open (&sb, G_VARIANT_TYPE_ARRAY);
3335   g_variant_builder_add (&sb, "s", "some value");
3336   g_variant_builder_clear (&sb);
3337
3338   g_variant_type_info_assert_no_infos ();
3339 }
3340
3341 static void
3342 test_hashing (void)
3343 {
3344   const gint n_items = 4096;
3345   GVariant *items[n_items];
3346   GHashTable *table;
3347   gint i;
3348
3349   table = g_hash_table_new_full (g_variant_hash, g_variant_equal,
3350                                  (GDestroyNotify ) g_variant_unref,
3351                                  NULL);
3352
3353   for (i = 0; i < n_items; i++)
3354     {
3355       TreeInstance *tree;
3356       gint j;
3357
3358  again:
3359       tree = tree_instance_new (NULL, 0);
3360       items[i] = tree_instance_get_gvariant (tree);
3361       tree_instance_free (tree);
3362
3363       for (j = 0; j < i; j++)
3364         if (g_variant_equal (items[i], items[j]))
3365           {
3366             g_variant_unref (items[i]);
3367             goto again;
3368           }
3369
3370       g_hash_table_insert (table,
3371                            g_variant_ref_sink (items[i]),
3372                            GINT_TO_POINTER (i));
3373     }
3374
3375   for (i = 0; i < n_items; i++)
3376     {
3377       gpointer result;
3378
3379       result = g_hash_table_lookup (table, items[i]);
3380       g_assert_cmpint (GPOINTER_TO_INT (result), ==, i);
3381     }
3382
3383   g_hash_table_unref (table);
3384
3385   g_variant_type_info_assert_no_infos ();
3386 }
3387
3388 int
3389 main (int argc, char **argv)
3390 {
3391   gint i;
3392
3393   g_test_init (&argc, &argv, NULL);
3394
3395   g_test_add_func ("/gvariant/type", test_gvarianttype);
3396   g_test_add_func ("/gvariant/typeinfo", test_gvarianttypeinfo);
3397   g_test_add_func ("/gvariant/serialiser/maybe", test_maybes);
3398   g_test_add_func ("/gvariant/serialiser/array", test_arrays);
3399   g_test_add_func ("/gvariant/serialiser/tuple", test_tuples);
3400   g_test_add_func ("/gvariant/serialiser/variant", test_variants);
3401   g_test_add_func ("/gvariant/serialiser/strings", test_strings);
3402   g_test_add_func ("/gvariant/serialiser/byteswap", test_byteswaps);
3403
3404   for (i = 1; i <= 20; i += 4)
3405     {
3406       char *testname;
3407
3408       testname = g_strdup_printf ("/gvariant/serialiser/fuzz/%d%%", i);
3409       g_test_add_data_func (testname, GINT_TO_POINTER (i),
3410                             (gpointer) test_fuzzes);
3411       g_free (testname);
3412     }
3413
3414   g_test_add_func ("/gvariant/containers", test_containers);
3415   g_test_add_func ("/gvariant/format-strings", test_format_strings);
3416   g_test_add_func ("/gvariant/invalid-varargs", test_invalid_varargs);
3417   g_test_add_func ("/gvariant/varargs", test_varargs);
3418   g_test_add_func ("/gvariant/valist", test_valist);
3419   g_test_add_func ("/gvariant/builder-memory", test_builder_memory);
3420   g_test_add_func ("/gvariant/hashing", test_hashing);
3421
3422   return g_test_run ();
3423 }