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