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