GVariant tests: test with larger strings
[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         if (serialised.size)
1524           g_assert (memcmp (serialised.data, data, serialised.size) == 0);
1525
1526         g_assert (g_variant_serialised_n_children (serialised) == n_children);
1527
1528         for (i = 0; i < n_children; i++)
1529           {
1530             GVariantSerialised child;
1531
1532             child = g_variant_serialised_get_child (serialised, i);
1533             g_assert (child.type_info == instances[i]->type_info);
1534             random_instance_assert (instances[i], child.data, child.size);
1535             g_variant_type_info_unref (child.type_info);
1536           }
1537
1538         flavoured_free (serialised.data, flavour);
1539       }
1540   }
1541
1542   {
1543     guint i;
1544
1545     for (i = 0; i < n_children; i++)
1546       random_instance_free (instances[i]);
1547     g_free (instances);
1548   }
1549
1550   g_variant_type_info_unref (element_info);
1551   g_variant_type_info_unref (array_info);
1552   align_free (data);
1553 }
1554
1555 static void
1556 test_arrays (void)
1557 {
1558   guint i;
1559
1560   for (i = 0; i < 100; i++)
1561     test_array ();
1562
1563   g_variant_type_info_assert_no_infos ();
1564 }
1565
1566 static void
1567 test_tuple (void)
1568 {
1569   GVariantTypeInfo *type_info;
1570   RandomInstance **instances;
1571   gboolean fixed_size;
1572   gsize needed_size;
1573   gsize offset_size;
1574   guint n_children;
1575   guint alignment;
1576   guchar *data;
1577
1578   n_children = g_test_rand_int_range (0, MAX_TUPLE_CHILDREN);
1579   instances = g_new (RandomInstance *, n_children);
1580
1581   {
1582     GString *type_string;
1583     guint i;
1584
1585     fixed_size = TRUE;
1586     alignment = 0;
1587
1588     type_string = g_string_new ("(");
1589     for (i = 0; i < n_children; i++)
1590       {
1591         const gchar *str;
1592
1593         instances[i] = random_instance (NULL);
1594
1595         alignment |= instances[i]->alignment;
1596         if (!instances[i]->is_fixed_sized)
1597           fixed_size = FALSE;
1598
1599         str = g_variant_type_info_get_type_string (instances[i]->type_info);
1600         g_string_append (type_string, str);
1601       }
1602     g_string_append_c (type_string, ')');
1603
1604     type_info = g_variant_type_info_get (G_VARIANT_TYPE (type_string->str));
1605     g_string_free (type_string, TRUE);
1606   }
1607
1608   needed_size = g_variant_serialiser_needed_size (type_info,
1609                                                   random_instance_filler,
1610                                                   (gpointer *) instances,
1611                                                   n_children);
1612   {
1613     gsize body_size = 0;
1614     gsize offsets = 0;
1615     guint i;
1616
1617     for (i = 0; i < n_children; i++)
1618       {
1619         append_instance_size (instances[i], &body_size);
1620
1621         if (i != n_children - 1 && !instances[i]->is_fixed_sized)
1622           offsets++;
1623       }
1624
1625     if (fixed_size)
1626       {
1627         body_size += (-body_size) & alignment;
1628
1629         g_assert ((body_size == 0) == (n_children == 0));
1630         if (n_children == 0)
1631           body_size = 1;
1632       }
1633
1634     offset_size = calculate_offset_size (body_size, offsets);
1635     g_assert_cmpint (needed_size, ==, body_size + offsets * offset_size);
1636   }
1637
1638   {
1639     guchar *body_ptr;
1640     guchar *ofs_ptr;
1641     guint i;
1642
1643     body_ptr = data = align_malloc (needed_size);
1644     ofs_ptr = body_ptr + needed_size;
1645
1646     for (i = 0; i < n_children; i++)
1647       {
1648         append_instance_data (instances[i], &body_ptr);
1649
1650         if (i != n_children - 1 && !instances[i]->is_fixed_sized)
1651           prepend_offset (&ofs_ptr, body_ptr - data, offset_size);
1652       }
1653
1654     if (fixed_size)
1655       {
1656         while (((gsize) body_ptr) & alignment)
1657           *body_ptr++ = '\0';
1658
1659         g_assert ((body_ptr == data) == (n_children == 0));
1660         if (n_children == 0)
1661           *body_ptr++ = '\0';
1662
1663       }
1664
1665
1666     g_assert (body_ptr == ofs_ptr);
1667   }
1668
1669   {
1670     gsize flavour;
1671     guint i;
1672
1673     alignment = (alignment & ALIGN_BITS) + 1;
1674
1675     for (flavour = 0; flavour < 8; flavour += alignment)
1676       {
1677         GVariantSerialised serialised;
1678
1679         serialised.type_info = type_info;
1680         serialised.data = flavoured_malloc (needed_size, flavour);
1681         serialised.size = needed_size;
1682
1683         g_variant_serialiser_serialise (serialised, random_instance_filler,
1684                                         (gpointer *) instances, n_children);
1685
1686         if (serialised.size)
1687           g_assert (memcmp (serialised.data, data, serialised.size) == 0);
1688
1689         g_assert (g_variant_serialised_n_children (serialised) == n_children);
1690
1691         for (i = 0; i < n_children; i++)
1692           {
1693             GVariantSerialised child;
1694
1695             child = g_variant_serialised_get_child (serialised, i);
1696             g_assert (child.type_info == instances[i]->type_info);
1697             random_instance_assert (instances[i], child.data, child.size);
1698             g_variant_type_info_unref (child.type_info);
1699           }
1700
1701         flavoured_free (serialised.data, flavour);
1702       }
1703   }
1704
1705   {
1706     guint i;
1707
1708     for (i = 0; i < n_children; i++)
1709       random_instance_free (instances[i]);
1710     g_free (instances);
1711   }
1712
1713   g_variant_type_info_unref (type_info);
1714   align_free (data);
1715 }
1716
1717 static void
1718 test_tuples (void)
1719 {
1720   guint i;
1721
1722   for (i = 0; i < 100; i++)
1723     test_tuple ();
1724
1725   g_variant_type_info_assert_no_infos ();
1726 }
1727
1728 static void
1729 test_variant (void)
1730 {
1731   GVariantTypeInfo *type_info;
1732   RandomInstance *instance;
1733   const gchar *type_string;
1734   gsize needed_size;
1735   guchar *data;
1736   gsize len;
1737
1738   type_info = g_variant_type_info_get (G_VARIANT_TYPE_VARIANT);
1739   instance = random_instance (NULL);
1740
1741   type_string = g_variant_type_info_get_type_string (instance->type_info);
1742   len = strlen (type_string);
1743
1744   needed_size = g_variant_serialiser_needed_size (type_info,
1745                                                   random_instance_filler,
1746                                                   (gpointer *) &instance, 1);
1747
1748   g_assert_cmpint (needed_size, ==, instance->size + 1 + len);
1749
1750   {
1751     guchar *ptr;
1752
1753     ptr = data = align_malloc (needed_size);
1754     append_instance_data (instance, &ptr);
1755     *ptr++ = '\0';
1756     memcpy (ptr, type_string, len);
1757     ptr += len;
1758
1759     g_assert (data + needed_size == ptr);
1760   }
1761
1762   {
1763     gsize alignment;
1764     gsize flavour;
1765
1766     /* variants are always 8-aligned */
1767     alignment = ALIGN_BITS + 1;
1768
1769     for (flavour = 0; flavour < 8; flavour += alignment)
1770       {
1771         GVariantSerialised serialised;
1772         GVariantSerialised child;
1773
1774         serialised.type_info = type_info;
1775         serialised.data = flavoured_malloc (needed_size, flavour);
1776         serialised.size = needed_size;
1777
1778         g_variant_serialiser_serialise (serialised, random_instance_filler,
1779                                         (gpointer *) &instance, 1);
1780
1781         if (serialised.size)
1782           g_assert (memcmp (serialised.data, data, serialised.size) == 0);
1783
1784         g_assert (g_variant_serialised_n_children (serialised) == 1);
1785
1786         child = g_variant_serialised_get_child (serialised, 0);
1787         g_assert (child.type_info == instance->type_info);
1788         random_instance_check (instance, child.data, child.size);
1789
1790         g_variant_type_info_unref (child.type_info);
1791         flavoured_free (serialised.data, flavour);
1792       }
1793   }
1794
1795   g_variant_type_info_unref (type_info);
1796   random_instance_free (instance);
1797   align_free (data);
1798 }
1799
1800 static void
1801 test_variants (void)
1802 {
1803   guint i;
1804
1805   for (i = 0; i < 100; i++)
1806     test_variant ();
1807
1808   g_variant_type_info_assert_no_infos ();
1809 }
1810
1811 static void
1812 test_strings (void)
1813 {
1814   struct {
1815     guint flags;
1816     guint size;
1817     gconstpointer data;
1818   } test_cases[] = {
1819 #define is_nval           0
1820 #define is_string         1
1821 #define is_objpath        is_string | 2
1822 #define is_sig            is_string | 4
1823     { is_sig,       1, "" },
1824     { is_nval,      0, NULL },
1825     { is_nval,     13, "hello\xffworld!" },
1826     { is_string,   13, "hello world!" },
1827     { is_nval,     13, "hello world\0" },
1828     { is_nval,     13, "hello\0world!" },
1829     { is_nval,     12, "hello world!" },
1830     { is_nval,     13, "hello world!\xff" },
1831
1832     { is_objpath,   2, "/" },
1833     { is_objpath,   3, "/a" },
1834     { is_string,    3, "//" },
1835     { is_objpath,  11, "/some/path" },
1836     { is_string,   12, "/some/path/" },
1837     { is_nval,     11, "/some\0path" },
1838     { is_string,   11, "/some\\path" },
1839     { is_string,   12, "/some//path" },
1840     { is_string,   12, "/some-/path" },
1841
1842     { is_sig,       2, "i" },
1843     { is_sig,       2, "s" },
1844     { is_sig,       5, "(si)" },
1845     { is_string,    4, "(si" },
1846     { is_string,    2, "*" },
1847     { is_sig,       3, "ai" },
1848     { is_string,    3, "mi" },
1849     { is_string,    2, "r" },
1850     { is_sig,      15, "(yyy{sv}ssiai)" },
1851     { is_string,   16, "(yyy{yv}ssiai))" },
1852     { is_string,   15, "(yyy{vv}ssiai)" },
1853     { is_string,   15, "(yyy{sv)ssiai}" }
1854   };
1855   guint i;
1856
1857   for (i = 0; i < G_N_ELEMENTS (test_cases); i++)
1858     {
1859       guint flags;
1860
1861       flags = g_variant_serialiser_is_string (test_cases[i].data,
1862                                               test_cases[i].size)
1863         ? 1 : 0;
1864
1865       flags |= g_variant_serialiser_is_object_path (test_cases[i].data,
1866                                                     test_cases[i].size)
1867         ? 2 : 0;
1868
1869       flags |= g_variant_serialiser_is_signature (test_cases[i].data,
1870                                                   test_cases[i].size)
1871         ? 4 : 0;
1872
1873       g_assert (flags == test_cases[i].flags);
1874     }
1875 }
1876
1877 typedef struct _TreeInstance TreeInstance;
1878 struct _TreeInstance
1879 {
1880   GVariantTypeInfo *info;
1881
1882   TreeInstance **children;
1883   gsize n_children;
1884
1885   union {
1886     guint64 integer;
1887     gdouble floating;
1888     gchar string[200];
1889   } data;
1890   gsize data_size;
1891 };
1892
1893 static GVariantType *
1894 make_random_definite_type (int depth)
1895 {
1896   GString *description;
1897   GString *type_string;
1898   GVariantType *type;
1899
1900   description = g_string_new (NULL);
1901   type_string = g_string_new (NULL);
1902   type = append_type_string (type_string, description, TRUE, depth);
1903   g_string_free (description, TRUE);
1904   g_string_free (type_string, TRUE);
1905
1906   return type;
1907 }
1908
1909 static void
1910 make_random_string (gchar              *string,
1911                     gsize               size,
1912                     const GVariantType *type)
1913 {
1914   gint i;
1915
1916   /* create strings that are valid signature strings */
1917 #define good_chars "bynqiuxthdsog"
1918
1919   for (i = 0; i < size - 1; i++)
1920     string[i] = good_chars[g_test_rand_int_range (0, strlen (good_chars))];
1921   string[i] = '\0';
1922
1923   /* in case we need an object path, prefix a '/' */
1924   if (*g_variant_type_peek_string (type) == 'o')
1925     string[0] = '/';
1926
1927 #undef good_chars
1928 }
1929
1930 static TreeInstance *
1931 tree_instance_new (const GVariantType *type,
1932                    int                 depth)
1933 {
1934   const GVariantType *child_type = NULL;
1935   GVariantType *mytype = NULL;
1936   TreeInstance *instance;
1937   gboolean is_tuple_type;
1938
1939   if (type == NULL)
1940     type = mytype = make_random_definite_type (depth);
1941
1942   instance = g_slice_new (TreeInstance);
1943   instance->info = g_variant_type_info_get (type);
1944   instance->children = NULL;
1945   instance->n_children = 0;
1946   instance->data_size = 0;
1947
1948   is_tuple_type = FALSE;
1949
1950   switch (*g_variant_type_peek_string (type))
1951     {
1952     case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
1953       instance->n_children = g_test_rand_int_range (0, 2);
1954       child_type = g_variant_type_element (type);
1955       break;
1956
1957     case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
1958       instance->n_children = g_test_rand_int_range (0, MAX_ARRAY_CHILDREN);
1959       child_type = g_variant_type_element (type);
1960       break;
1961
1962     case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
1963     case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
1964       instance->n_children = g_variant_type_n_items (type);
1965       child_type = g_variant_type_first (type);
1966       is_tuple_type = TRUE;
1967       break;
1968
1969     case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
1970       instance->n_children = 1;
1971       child_type = NULL;
1972       break;
1973
1974     case 'b':
1975       instance->data.integer = g_test_rand_int_range (0, 2);
1976       instance->data_size = 1;
1977       break;
1978
1979     case 'y':
1980       instance->data.integer = g_test_rand_int ();
1981       instance->data_size = 1;
1982       break;
1983
1984     case 'n': case 'q':
1985       instance->data.integer = g_test_rand_int ();
1986       instance->data_size = 2;
1987       break;
1988
1989     case 'i': case 'u': case 'h':
1990       instance->data.integer = g_test_rand_int ();
1991       instance->data_size = 4;
1992       break;
1993
1994     case 'x': case 't':
1995       instance->data.integer = g_test_rand_int ();
1996       instance->data.integer <<= 32;
1997       instance->data.integer |= (guint32) g_test_rand_int ();
1998       instance->data_size = 8;
1999       break;
2000
2001     case 'd':
2002       instance->data.floating = g_test_rand_double ();
2003       instance->data_size = 8;
2004       break;
2005
2006     case 's': case 'o': case 'g':
2007       instance->data_size = g_test_rand_int_range (10, 200);
2008       make_random_string (instance->data.string, instance->data_size, type);
2009       break;
2010     }
2011
2012   if (instance->data_size == 0)
2013     /* no data -> it is a container */
2014     {
2015       guint i;
2016
2017       instance->children = g_new (TreeInstance *, instance->n_children);
2018
2019       for (i = 0; i < instance->n_children; i++)
2020         {
2021           instance->children[i] = tree_instance_new (child_type, depth - 1);
2022
2023           if (is_tuple_type)
2024             child_type = g_variant_type_next (child_type);
2025         }
2026
2027       g_assert (!is_tuple_type || child_type == NULL);
2028     }
2029
2030   g_variant_type_free (mytype);
2031
2032   return instance;
2033 }
2034
2035 static void
2036 tree_instance_free (TreeInstance *instance)
2037 {
2038   gint i;
2039
2040   g_variant_type_info_unref (instance->info);
2041   for (i = 0; i < instance->n_children; i++)
2042     tree_instance_free (instance->children[i]);
2043   g_free (instance->children);
2044   g_slice_free (TreeInstance, instance);
2045 }
2046
2047 static gboolean i_am_writing_byteswapped;
2048
2049 static void
2050 tree_filler (GVariantSerialised *serialised,
2051              gpointer            data)
2052 {
2053   TreeInstance *instance = data;
2054
2055   if (serialised->type_info == NULL)
2056     serialised->type_info = instance->info;
2057
2058   if (instance->data_size == 0)
2059     /* is a container */
2060     {
2061       if (serialised->size == 0)
2062         serialised->size =
2063           g_variant_serialiser_needed_size (instance->info, tree_filler,
2064                                             (gpointer *) instance->children,
2065                                             instance->n_children);
2066
2067       if (serialised->data)
2068         g_variant_serialiser_serialise (*serialised, tree_filler,
2069                                         (gpointer *) instance->children,
2070                                         instance->n_children);
2071     }
2072   else
2073     /* it is a leaf */
2074     {
2075       if (serialised->size == 0)
2076         serialised->size = instance->data_size;
2077
2078       if (serialised->data)
2079         {
2080           switch (instance->data_size)
2081             {
2082             case 1:
2083               *serialised->data = instance->data.integer;
2084               break;
2085
2086             case 2:
2087               {
2088                 guint16 value = instance->data.integer;
2089
2090                 if (i_am_writing_byteswapped)
2091                   value = GUINT16_SWAP_LE_BE (value);
2092
2093                 *(guint16 *) serialised->data = value;
2094               }
2095               break;
2096
2097             case 4:
2098               {
2099                 guint32 value = instance->data.integer;
2100
2101                 if (i_am_writing_byteswapped)
2102                   value = GUINT32_SWAP_LE_BE (value);
2103
2104                 *(guint32 *) serialised->data = value;
2105               }
2106               break;
2107
2108             case 8:
2109               {
2110                 guint64 value = instance->data.integer;
2111
2112                 if (i_am_writing_byteswapped)
2113                   value = GUINT64_SWAP_LE_BE (value);
2114
2115                 *(guint64 *) serialised->data = value;
2116               }
2117               break;
2118
2119             default:
2120               memcpy (serialised->data,
2121                       instance->data.string,
2122                       instance->data_size);
2123               break;
2124             }
2125         }
2126     }
2127 }
2128
2129 static gboolean
2130 check_tree (TreeInstance       *instance,
2131             GVariantSerialised  serialised)
2132 {
2133   if (instance->info != serialised.type_info)
2134     return FALSE;
2135
2136   if (instance->data_size == 0)
2137     /* is a container */
2138     {
2139       gint i;
2140
2141       if (g_variant_serialised_n_children (serialised) !=
2142           instance->n_children)
2143         return FALSE;
2144
2145       for (i = 0; i < instance->n_children; i++)
2146         {
2147           GVariantSerialised child;
2148           gpointer data = NULL;
2149           gboolean ok;
2150
2151           child = g_variant_serialised_get_child (serialised, i);
2152           if (child.size && child.data == NULL)
2153             child.data = data = g_malloc0 (child.size);
2154           ok = check_tree (instance->children[i], child);
2155           g_variant_type_info_unref (child.type_info);
2156           g_free (data);
2157
2158           if (!ok)
2159             return FALSE;
2160         }
2161
2162       return TRUE;
2163     }
2164   else
2165     /* it is a leaf */
2166     {
2167       switch (instance->data_size)
2168         {
2169         case 1:
2170           g_assert (serialised.size == 1);
2171           return *(guint8 *) serialised.data ==
2172                   (guint8) instance->data.integer;
2173
2174         case 2:
2175           g_assert (serialised.size == 2);
2176           return *(guint16 *) serialised.data ==
2177                   (guint16) instance->data.integer;
2178
2179         case 4:
2180           g_assert (serialised.size == 4);
2181           return *(guint32 *) serialised.data ==
2182                   (guint32) instance->data.integer;
2183
2184         case 8:
2185           g_assert (serialised.size == 8);
2186           return *(guint64 *) serialised.data ==
2187                   (guint64) instance->data.integer;
2188
2189         default:
2190           if (serialised.size != instance->data_size)
2191             return FALSE;
2192
2193           return memcmp (serialised.data,
2194                          instance->data.string,
2195                          instance->data_size) == 0;
2196         }
2197     }
2198 }
2199
2200 static void
2201 serialise_tree (TreeInstance       *tree,
2202                 GVariantSerialised *serialised)
2203 {
2204   GVariantSerialised empty = {0, };
2205
2206   *serialised = empty;
2207   tree_filler (serialised, tree);
2208   serialised->data = g_malloc (serialised->size);
2209   tree_filler (serialised, tree);
2210 }
2211
2212 static void
2213 test_byteswap (void)
2214 {
2215   GVariantSerialised one, two;
2216   TreeInstance *tree;
2217
2218   tree = tree_instance_new (NULL, 3);
2219   serialise_tree (tree, &one);
2220
2221   i_am_writing_byteswapped = TRUE;
2222   serialise_tree (tree, &two);
2223   i_am_writing_byteswapped = FALSE;
2224
2225   g_variant_serialised_byteswap (two);
2226
2227   g_assert_cmpint (one.size, ==, two.size);
2228   g_assert (memcmp (one.data, two.data, one.size) == 0);
2229
2230   tree_instance_free (tree);
2231   g_free (one.data);
2232   g_free (two.data);
2233 }
2234
2235 static void
2236 test_byteswaps (void)
2237 {
2238   int i;
2239
2240   for (i = 0; i < 200; i++)
2241     test_byteswap ();
2242
2243   g_variant_type_info_assert_no_infos ();
2244 }
2245
2246 static void
2247 test_fuzz (gdouble *fuzziness)
2248 {
2249   GVariantSerialised serialised;
2250   TreeInstance *tree;
2251
2252   /* make an instance */
2253   tree = tree_instance_new (NULL, 3);
2254
2255   /* serialise it */
2256   serialise_tree (tree, &serialised);
2257
2258   g_assert (g_variant_serialised_is_normal (serialised));
2259   g_assert (check_tree (tree, serialised));
2260
2261   if (serialised.size)
2262     {
2263       gboolean fuzzed = FALSE;
2264       gboolean a, b;
2265
2266       while (!fuzzed)
2267         {
2268           gint i;
2269
2270           for (i = 0; i < serialised.size; i++)
2271             if (randomly (*fuzziness))
2272               {
2273                 serialised.data[i] += g_test_rand_int_range (1, 256);
2274                 fuzzed = TRUE;
2275               }
2276         }
2277
2278       /* at least one byte in the serialised data has changed.
2279        *
2280        * this means that at least one of the following is true:
2281        *
2282        *    - the serialised data now represents a different value:
2283        *        check_tree() will return FALSE
2284        *
2285        *    - the serialised data is in non-normal form:
2286        *        g_variant_serialiser_is_normal() will return FALSE
2287        *
2288        * we always do both checks to increase exposure of the serialiser
2289        * to corrupt data.
2290        */
2291       a = g_variant_serialised_is_normal (serialised);
2292       b = check_tree (tree, serialised);
2293
2294       g_assert (!a || !b);
2295     }
2296
2297   tree_instance_free (tree);
2298   g_free (serialised.data);
2299 }
2300
2301
2302 static void
2303 test_fuzzes (gpointer data)
2304 {
2305   gdouble fuzziness;
2306   int i;
2307
2308   fuzziness = GPOINTER_TO_INT (data) / 100.;
2309
2310   for (i = 0; i < 200; i++)
2311     test_fuzz (&fuzziness);
2312
2313   g_variant_type_info_assert_no_infos ();
2314 }
2315
2316 static GVariant *
2317 tree_instance_get_gvariant (TreeInstance *tree)
2318 {
2319   const GVariantType *type;
2320   GVariant *result;
2321
2322   type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
2323
2324   switch (g_variant_type_info_get_type_char (tree->info))
2325     {
2326     case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
2327       {
2328         const GVariantType *child_type;
2329         GVariant *child;
2330
2331         if (tree->n_children)
2332           child = tree_instance_get_gvariant (tree->children[0]);
2333         else
2334           child = NULL;
2335
2336         child_type = g_variant_type_element (type);
2337
2338         if (child != NULL && randomly (0.5))
2339           child_type = NULL;
2340
2341         result = g_variant_new_maybe (child_type, child);
2342       }
2343       break;
2344
2345     case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
2346       {
2347         const GVariantType *child_type;
2348         GVariant **children;
2349         gint i;
2350
2351         children = g_new (GVariant *, tree->n_children);
2352         for (i = 0; i < tree->n_children; i++)
2353           children[i] = tree_instance_get_gvariant (tree->children[i]);
2354
2355         child_type = g_variant_type_element (type);
2356
2357         if (i > 0 && randomly (0.5))
2358           child_type = NULL;
2359
2360         result = g_variant_new_array (child_type, children, tree->n_children);
2361         g_free (children);
2362       }
2363       break;
2364
2365     case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
2366       {
2367         GVariant **children;
2368         gint i;
2369
2370         children = g_new (GVariant *, tree->n_children);
2371         for (i = 0; i < tree->n_children; i++)
2372           children[i] = tree_instance_get_gvariant (tree->children[i]);
2373
2374         result = g_variant_new_tuple (children, tree->n_children);
2375         g_free (children);
2376       }
2377       break;
2378
2379     case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
2380       {
2381         GVariant *key, *val;
2382
2383         g_assert (tree->n_children == 2);
2384
2385         key = tree_instance_get_gvariant (tree->children[0]);
2386         val = tree_instance_get_gvariant (tree->children[1]);
2387
2388         result = g_variant_new_dict_entry (key, val);
2389       }
2390       break;
2391
2392     case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
2393       {
2394         GVariant *value;
2395
2396         g_assert (tree->n_children == 1);
2397
2398         value = tree_instance_get_gvariant (tree->children[0]);
2399         result = g_variant_new_variant (value);
2400       }
2401       break;
2402
2403     case 'b':
2404       result = g_variant_new_boolean (tree->data.integer > 0);
2405       break;
2406
2407     case 'y':
2408       result = g_variant_new_byte (tree->data.integer);
2409       break;
2410
2411     case 'n':
2412       result = g_variant_new_int16 (tree->data.integer);
2413       break;
2414
2415     case 'q':
2416       result = g_variant_new_uint16 (tree->data.integer);
2417       break;
2418
2419     case 'i':
2420       result = g_variant_new_int32 (tree->data.integer);
2421       break;
2422
2423     case 'u':
2424       result = g_variant_new_uint32 (tree->data.integer);
2425       break;
2426
2427     case 'x':
2428       result = g_variant_new_int64 (tree->data.integer);
2429       break;
2430
2431     case 't':
2432       result = g_variant_new_uint64 (tree->data.integer);
2433       break;
2434
2435     case 'h':
2436       result = g_variant_new_handle (tree->data.integer);
2437       break;
2438
2439     case 'd':
2440       result = g_variant_new_double (tree->data.floating);
2441       break;
2442
2443     case 's':
2444       result = g_variant_new_string (tree->data.string);
2445       break;
2446
2447     case 'o':
2448       result = g_variant_new_object_path (tree->data.string);
2449       break;
2450
2451     case 'g':
2452       result = g_variant_new_signature (tree->data.string);
2453       break;
2454
2455     default:
2456       g_assert_not_reached ();
2457     }
2458
2459   return result;
2460 }
2461
2462 static gboolean
2463 tree_instance_check_gvariant (TreeInstance *tree,
2464                               GVariant     *value)
2465 {
2466   const GVariantType *type;
2467
2468   type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
2469   g_assert (g_variant_is_of_type (value, type));
2470
2471   switch (g_variant_type_info_get_type_char (tree->info))
2472     {
2473     case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
2474       {
2475         GVariant *child;
2476         gboolean equal;
2477
2478         child = g_variant_get_maybe (value);
2479
2480         if (child != NULL && tree->n_children == 1)
2481           equal = tree_instance_check_gvariant (tree->children[0], child);
2482         else if (child == NULL && tree->n_children == 0)
2483           equal = TRUE;
2484         else
2485           equal = FALSE;
2486
2487         if (child != NULL)
2488           g_variant_unref (child);
2489
2490         return equal;
2491       }
2492       break;
2493
2494     case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
2495     case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
2496     case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
2497       {
2498         gsize i;
2499
2500         if (g_variant_n_children (value) != tree->n_children)
2501           return FALSE;
2502
2503         for (i = 0; i < tree->n_children; i++)
2504           {
2505             GVariant *child;
2506             gboolean equal;
2507
2508             child = g_variant_get_child_value (value, i);
2509             equal = tree_instance_check_gvariant (tree->children[i], child);
2510             g_variant_unref (child);
2511
2512             if (!equal)
2513               return FALSE;
2514           }
2515
2516         return TRUE;
2517       }
2518       break;
2519
2520     case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
2521       {
2522         const gchar *str1, *str2;
2523         GVariant *child;
2524         gboolean equal;
2525
2526         child = g_variant_get_variant (value);
2527         str1 = g_variant_get_type_string (child);
2528         str2 = g_variant_type_info_get_type_string (tree->children[0]->info);
2529         /* GVariant only keeps one copy of type strings around */
2530         equal = str1 == str2 &&
2531                 tree_instance_check_gvariant (tree->children[0], child);
2532
2533         g_variant_unref (child);
2534
2535         return equal;
2536       }
2537       break;
2538
2539     case 'b':
2540       return g_variant_get_boolean (value) == tree->data.integer;
2541
2542     case 'y':
2543       return g_variant_get_byte (value) == (guchar) tree->data.integer;
2544
2545     case 'n':
2546       return g_variant_get_int16 (value) == (gint16) tree->data.integer;
2547
2548     case 'q':
2549       return g_variant_get_uint16 (value) == (guint16) tree->data.integer;
2550
2551     case 'i':
2552       return g_variant_get_int32 (value) == (gint32) tree->data.integer;
2553
2554     case 'u':
2555       return g_variant_get_uint32 (value) == (guint32) tree->data.integer;
2556
2557     case 'x':
2558       return g_variant_get_int64 (value) == (gint64) tree->data.integer;
2559
2560     case 't':
2561       return g_variant_get_uint64 (value) == (guint64) tree->data.integer;
2562
2563     case 'h':
2564       return g_variant_get_handle (value) == (gint32) tree->data.integer;
2565
2566     case 'd':
2567       {
2568         gdouble floating = g_variant_get_double (value);
2569
2570         return memcmp (&floating, &tree->data.floating, sizeof floating) == 0;
2571       }
2572
2573     case 's':
2574     case 'o':
2575     case 'g':
2576       return strcmp (g_variant_get_string (value, NULL),
2577                      tree->data.string) == 0;
2578
2579     default:
2580       g_assert_not_reached ();
2581     }
2582 }
2583
2584 static void
2585 tree_instance_build_gvariant (TreeInstance    *tree,
2586                               GVariantBuilder *builder,
2587                               gboolean         guess_ok)
2588 {
2589   const GVariantType *type;
2590
2591   type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
2592
2593   if (g_variant_type_is_container (type))
2594     {
2595       gsize i;
2596
2597       /* force GVariantBuilder to guess the type half the time */
2598       if (guess_ok && randomly (0.5))
2599         {
2600           if (g_variant_type_is_array (type) && tree->n_children)
2601             type = G_VARIANT_TYPE_ARRAY;
2602
2603           if (g_variant_type_is_maybe (type) && tree->n_children)
2604             type = G_VARIANT_TYPE_MAYBE;
2605
2606           if (g_variant_type_is_tuple (type))
2607             type = G_VARIANT_TYPE_TUPLE;
2608
2609           if (g_variant_type_is_dict_entry (type))
2610             type = G_VARIANT_TYPE_DICT_ENTRY;
2611         }
2612       else
2613         guess_ok = FALSE;
2614
2615       g_variant_builder_open (builder, type);
2616
2617       for (i = 0; i < tree->n_children; i++)
2618         tree_instance_build_gvariant (tree->children[i], builder, guess_ok);
2619
2620       g_variant_builder_close (builder);
2621     }
2622   else
2623     g_variant_builder_add_value (builder, tree_instance_get_gvariant (tree));
2624 }
2625
2626
2627 static gboolean
2628 tree_instance_check_iter (TreeInstance *tree,
2629                           GVariantIter *iter)
2630 {
2631   GVariant *value;
2632
2633   value = g_variant_iter_next_value (iter);
2634
2635   if (g_variant_is_container (value))
2636     {
2637       gsize i;
2638
2639       iter = g_variant_iter_new (value);
2640       g_variant_unref (value);
2641
2642       if (g_variant_iter_n_children (iter) != tree->n_children)
2643         {
2644           g_variant_iter_free (iter);
2645           return FALSE;
2646         }
2647
2648       for (i = 0; i < tree->n_children; i++)
2649         if (!tree_instance_check_iter (tree->children[i], iter))
2650           {
2651             g_variant_iter_free (iter);
2652             return FALSE;
2653           }
2654
2655       g_assert (g_variant_iter_next_value (iter) == NULL);
2656       g_variant_iter_free (iter);
2657
2658       return TRUE;
2659     }
2660
2661   else
2662     {
2663       gboolean equal;
2664
2665       equal = tree_instance_check_gvariant (tree, value);
2666       g_variant_unref (value);
2667
2668       return equal;
2669     }
2670 }
2671
2672 static void
2673 test_container (void)
2674 {
2675   TreeInstance *tree;
2676   GVariant *value;
2677   gchar *s1, *s2;
2678
2679   tree = tree_instance_new (NULL, 3);
2680   value = g_variant_ref_sink (tree_instance_get_gvariant (tree));
2681
2682   s1 = g_variant_print (value, TRUE);
2683   g_assert (tree_instance_check_gvariant (tree, value));
2684
2685   g_variant_get_data (value);
2686
2687   s2 = g_variant_print (value, TRUE);
2688   g_assert (tree_instance_check_gvariant (tree, value));
2689
2690   g_assert_cmpstr (s1, ==, s2);
2691
2692   if (g_variant_is_container (value))
2693     {
2694       GVariantBuilder builder;
2695       GVariantIter iter;
2696       GVariant *built;
2697       GVariant *val;
2698       gchar *s3;
2699
2700       g_variant_builder_init (&builder, G_VARIANT_TYPE_VARIANT);
2701       tree_instance_build_gvariant (tree, &builder, TRUE);
2702       built = g_variant_builder_end (&builder);
2703       g_variant_ref_sink (built);
2704       g_variant_get_data (built);
2705       val = g_variant_get_variant (built);
2706
2707       s3 = g_variant_print (val, TRUE);
2708       g_assert_cmpstr (s1, ==, s3);
2709
2710       g_variant_iter_init (&iter, built);
2711       g_assert (tree_instance_check_iter (tree, &iter));
2712       g_assert (g_variant_iter_next_value (&iter) == NULL);
2713
2714       g_variant_unref (built);
2715       g_variant_unref (val);
2716       g_free (s3);
2717     }
2718
2719   tree_instance_free (tree);
2720   g_variant_unref (value);
2721   g_free (s2);
2722   g_free (s1);
2723 }
2724
2725 static void
2726 test_string (void)
2727 {
2728   /* Test some different methods of creating strings */
2729   GVariant *v;
2730
2731   v = g_variant_new_string ("foo");
2732   g_assert_cmpstr (g_variant_get_string (v, NULL), ==, "foo");
2733   g_variant_unref (v);
2734
2735
2736   v = g_variant_new_take_string (g_strdup ("foo"));
2737   g_assert_cmpstr (g_variant_get_string (v, NULL), ==, "foo");
2738   g_variant_unref (v);
2739
2740   v = g_variant_new_printf ("%s %d", "foo", 123);
2741   g_assert_cmpstr (g_variant_get_string (v, NULL), ==, "foo 123");
2742   g_variant_unref (v);
2743 }
2744
2745 static void
2746 test_utf8 (void)
2747 {
2748   const gchar invalid[] = "hello\xffworld";
2749   GVariant *value;
2750
2751   /* ensure that the test data is not valid utf8... */
2752   g_assert (!g_utf8_validate (invalid, -1, NULL));
2753
2754   /* load the data untrusted */
2755   value = g_variant_new_from_data (G_VARIANT_TYPE_STRING,
2756                                    invalid, sizeof invalid,
2757                                    FALSE, NULL, NULL);
2758
2759   /* ensure that the problem is caught and we get valid UTF-8 */
2760   g_assert (g_utf8_validate (g_variant_get_string (value, NULL), -1, NULL));
2761   g_variant_unref (value);
2762
2763
2764   /* now load it trusted */
2765   value = g_variant_new_from_data (G_VARIANT_TYPE_STRING,
2766                                    invalid, sizeof invalid,
2767                                    TRUE, NULL, NULL);
2768
2769   /* ensure we get the invalid data (ie: make sure that time wasn't
2770    * wasted on validating data that was marked as trusted)
2771    */
2772   g_assert (g_variant_get_string (value, NULL) == invalid);
2773   g_variant_unref (value);
2774 }
2775
2776 static void
2777 test_containers (void)
2778 {
2779   gint i;
2780
2781   for (i = 0; i < 100; i++)
2782     {
2783       test_container ();
2784     }
2785
2786   g_variant_type_info_assert_no_infos ();
2787 }
2788
2789 static void
2790 test_format_strings (void)
2791 {
2792   GVariantType *type;
2793   const gchar *end;
2794
2795   g_assert (g_variant_format_string_scan ("i", NULL, &end) && *end == '\0');
2796   g_assert (g_variant_format_string_scan ("@i", NULL, &end) && *end == '\0');
2797   g_assert (g_variant_format_string_scan ("@ii", NULL, &end) && *end == 'i');
2798   g_assert (g_variant_format_string_scan ("^a&s", NULL, &end) && *end == '\0');
2799   g_assert (g_variant_format_string_scan ("(^as)", NULL, &end) &&
2800             *end == '\0');
2801   g_assert (!g_variant_format_string_scan ("(^s)", NULL, &end));
2802   g_assert (!g_variant_format_string_scan ("(^a)", NULL, &end));
2803   g_assert (!g_variant_format_string_scan ("(z)", NULL, &end));
2804   g_assert (!g_variant_format_string_scan ("az", NULL, &end));
2805   g_assert (!g_variant_format_string_scan ("{**}", NULL, &end));
2806   g_assert (!g_variant_format_string_scan ("{@**}", NULL, &end));
2807   g_assert (g_variant_format_string_scan ("{@y*}", NULL, &end) &&
2808             *end == '\0');
2809   g_assert (g_variant_format_string_scan ("{yv}", NULL, &end) &&
2810             *end == '\0');
2811   g_assert (!g_variant_format_string_scan ("{&?v}", NULL, &end));
2812   g_assert (g_variant_format_string_scan ("{@?v}", NULL, &end) &&
2813             *end == '\0');
2814   g_assert (!g_variant_format_string_scan ("{&@sv}", NULL, &end));
2815   g_assert (!g_variant_format_string_scan ("{@&sv}", NULL, &end));
2816   g_assert (g_variant_format_string_scan ("{&sv}", NULL, &end) &&
2817             *end == '\0');
2818   g_assert (!g_variant_format_string_scan ("{vv}", NULL, &end));
2819   g_assert (!g_variant_format_string_scan ("{y}", NULL, &end));
2820   g_assert (!g_variant_format_string_scan ("{yyy}", NULL, &end));
2821   g_assert (!g_variant_format_string_scan ("{ya}", NULL, &end));
2822   g_assert (g_variant_format_string_scan ("&s", NULL, &end) && *end == '\0');
2823   g_assert (!g_variant_format_string_scan ("&as", NULL, &end));
2824   g_assert (!g_variant_format_string_scan ("@z", NULL, &end));
2825   g_assert (!g_variant_format_string_scan ("az", NULL, &end));
2826   g_assert (!g_variant_format_string_scan ("a&s", NULL, &end));
2827
2828   type = g_variant_format_string_scan_type ("mm(@xy^a&s*?@?)", NULL, &end);
2829   g_assert (type && *end == '\0');
2830   g_assert (g_variant_type_equal (type, G_VARIANT_TYPE ("mm(xyas*?\?)")));
2831   g_variant_type_free (type);
2832
2833   type = g_variant_format_string_scan_type ("mm(@xy^a&*?@?)", NULL, NULL);
2834   g_assert (type == NULL);
2835 }
2836
2837 static void
2838 do_failed_test (const char *test,
2839                 const gchar *pattern)
2840 {
2841   g_test_trap_subprocess (test, 1000000, 0);
2842   g_test_trap_assert_failed ();
2843   g_test_trap_assert_stderr (pattern);
2844 }
2845
2846 static void
2847 test_invalid_varargs (void)
2848 {
2849   GVariant *value;
2850   const gchar *end;
2851
2852   if (!g_test_undefined ())
2853     return;
2854
2855   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
2856                          "*GVariant format string*");
2857   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
2858                          "*valid_format_string*");
2859   value = g_variant_new ("z");
2860   g_test_assert_expected_messages ();
2861   g_assert (value == NULL);
2862
2863   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
2864                          "*valid GVariant format string as a prefix*");
2865   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
2866                          "*valid_format_string*");
2867   value = g_variant_new_va ("z", &end, NULL);
2868   g_test_assert_expected_messages ();
2869   g_assert (value == NULL);
2870
2871   value = g_variant_new ("y", 'a');
2872   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
2873                          "*type of 'q' but * has a type of 'y'*");
2874   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
2875                          "*valid_format_string*");
2876   g_variant_get (value, "q");
2877   g_test_assert_expected_messages ();
2878   g_variant_unref (value);
2879 }
2880
2881 static void
2882 check_and_free (GVariant    *value,
2883                 const gchar *str)
2884 {
2885   gchar *valstr = g_variant_print (value, FALSE);
2886   g_assert_cmpstr (str, ==, valstr);
2887   g_variant_unref (value);
2888   g_free (valstr);
2889 }
2890
2891 static void
2892 test_varargs_empty_array (void)
2893 {
2894   g_variant_new ("(a{s*})", NULL);
2895
2896   g_assert_not_reached ();
2897 }
2898
2899 static void
2900 test_varargs (void)
2901 {
2902   {
2903     GVariantBuilder array;
2904
2905     g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
2906     g_variant_builder_add_parsed (&array, "{'size', <(%i, %i)> }", 800, 600);
2907     g_variant_builder_add (&array, "{sv}", "title",
2908                            g_variant_new_string ("Test case"));
2909     g_variant_builder_add_value (&array,
2910       g_variant_new_dict_entry (g_variant_new_string ("temperature"),
2911                                 g_variant_new_variant (
2912                                   g_variant_new_double (37.5))));
2913     check_and_free (g_variant_new ("(ma{sv}m(a{sv})ma{sv}ii)",
2914                                    NULL, FALSE, NULL, &array, 7777, 8888),
2915                     "(nothing, nothing, {'size': <(800, 600)>, "
2916                                         "'title': <'Test case'>, "
2917                                         "'temperature': <37.5>}, "
2918                      "7777, 8888)");
2919
2920     check_and_free (g_variant_new ("(imimimmimmimmi)",
2921                                    123,
2922                                    FALSE, 321,
2923                                    TRUE, 123,
2924                                    FALSE, TRUE, 321,
2925                                    TRUE, FALSE, 321,
2926                                    TRUE, TRUE, 123),
2927                     "(123, nothing, 123, nothing, just nothing, 123)");
2928
2929     check_and_free (g_variant_new ("(ybnixd)",
2930                                    'a', 1, 22, 33, (guint64) 44, 5.5),
2931                     "(0x61, true, 22, 33, 44, 5.5)");
2932
2933     check_and_free (g_variant_new ("(@y?*rv)",
2934                                    g_variant_new ("y", 'a'),
2935                                    g_variant_new ("y", 'b'),
2936                                    g_variant_new ("y", 'c'),
2937                                    g_variant_new ("(y)", 'd'),
2938                                    g_variant_new ("y", 'e')),
2939                     "(0x61, 0x62, 0x63, (0x64,), <byte 0x65>)");
2940   }
2941
2942   {
2943     GVariantBuilder array;
2944     GVariantIter iter;
2945     GVariant *value;
2946     gchar *number;
2947     gboolean just;
2948     gint i, val;
2949
2950     g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
2951     for (i = 0; i < 100; i++)
2952       {
2953         number = g_strdup_printf ("%d", i);
2954         g_variant_builder_add (&array, "s", number);
2955         g_free (number);
2956       }
2957
2958     value = g_variant_builder_end (&array);
2959     g_variant_iter_init (&iter, value);
2960
2961     i = 0;
2962     while (g_variant_iter_loop (&iter, "s", &number))
2963       {
2964         gchar *check = g_strdup_printf ("%d", i++);
2965         g_assert_cmpstr (number, ==, check);
2966         g_free (check);
2967       }
2968     g_assert (number == NULL);
2969     g_assert (i == 100);
2970
2971     g_variant_unref (value);
2972
2973     g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
2974     for (i = 0; i < 100; i++)
2975       g_variant_builder_add (&array, "mi", i % 2 == 0, i);
2976     value = g_variant_builder_end (&array);
2977
2978     i = 0;
2979     g_variant_iter_init (&iter, value);
2980     while (g_variant_iter_loop (&iter, "mi", NULL, &val))
2981       g_assert (val == i++ || val == 0);
2982     g_assert (i == 100);
2983
2984     i = 0;
2985     g_variant_iter_init (&iter, value);
2986     while (g_variant_iter_loop (&iter, "mi", &just, &val))
2987       {
2988         gint this = i++;
2989
2990         if (this % 2 == 0)
2991           {
2992             g_assert (just);
2993             g_assert (val == this);
2994           }
2995         else
2996           {
2997             g_assert (!just);
2998             g_assert (val == 0);
2999           }
3000       }
3001     g_assert (i == 100);
3002
3003     g_variant_unref (value);
3004   }
3005
3006   {
3007     const gchar *strvector[] = {"/hello", "/world", NULL};
3008     const gchar *test_strs[] = {"/foo", "/bar", "/baz" };
3009     GVariantBuilder builder;
3010     GVariantIter *array;
3011     GVariantIter tuple;
3012     const gchar **strv;
3013     gchar **my_strv;
3014     GVariant *value;
3015     gchar *str;
3016     gint i;
3017
3018     g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
3019     g_variant_builder_add (&builder, "s", "/foo");
3020     g_variant_builder_add (&builder, "s", "/bar");
3021     g_variant_builder_add (&builder, "s", "/baz");
3022     value = g_variant_new("(as^as^a&s)", &builder, strvector, strvector);
3023     g_variant_iter_init (&tuple, value);
3024     g_variant_iter_next (&tuple, "as", &array);
3025
3026     i = 0;
3027     while (g_variant_iter_loop (array, "s", &str))
3028       g_assert_cmpstr (str, ==, test_strs[i++]);
3029     g_assert (i == 3);
3030
3031     g_variant_iter_free (array);
3032
3033     /* start over */
3034     g_variant_iter_init (&tuple, value);
3035     g_variant_iter_next (&tuple, "as", &array);
3036
3037     i = 0;
3038     while (g_variant_iter_loop (array, "&s", &str))
3039       g_assert_cmpstr (str, ==, test_strs[i++]);
3040     g_assert (i == 3);
3041
3042     g_variant_iter_free (array);
3043
3044     g_variant_iter_next (&tuple, "^a&s", &strv);
3045     g_variant_iter_next (&tuple, "^as", &my_strv);
3046
3047     g_assert_cmpstr (strv[0], ==, "/hello");
3048     g_assert_cmpstr (strv[1], ==, "/world");
3049     g_assert (strv[2] == NULL);
3050     g_assert_cmpstr (my_strv[0], ==, "/hello");
3051     g_assert_cmpstr (my_strv[1], ==, "/world");
3052     g_assert (my_strv[2] == NULL);
3053
3054     g_variant_unref (value);
3055     g_strfreev (my_strv);
3056     g_free (strv);
3057   }
3058
3059   {
3060     const gchar *strvector[] = {"/hello", "/world", NULL};
3061     const gchar *test_strs[] = {"/foo", "/bar", "/baz" };
3062     GVariantBuilder builder;
3063     GVariantIter *array;
3064     GVariantIter tuple;
3065     const gchar **strv;
3066     gchar **my_strv;
3067     GVariant *value;
3068     gchar *str;
3069     gint i;
3070
3071     g_variant_builder_init (&builder, G_VARIANT_TYPE_OBJECT_PATH_ARRAY);
3072     g_variant_builder_add (&builder, "o", "/foo");
3073     g_variant_builder_add (&builder, "o", "/bar");
3074     g_variant_builder_add (&builder, "o", "/baz");
3075     value = g_variant_new("(ao^ao^a&o)", &builder, strvector, strvector);
3076     g_variant_iter_init (&tuple, value);
3077     g_variant_iter_next (&tuple, "ao", &array);
3078
3079     i = 0;
3080     while (g_variant_iter_loop (array, "o", &str))
3081       g_assert_cmpstr (str, ==, test_strs[i++]);
3082     g_assert (i == 3);
3083
3084     g_variant_iter_free (array);
3085
3086     /* start over */
3087     g_variant_iter_init (&tuple, value);
3088     g_variant_iter_next (&tuple, "ao", &array);
3089
3090     i = 0;
3091     while (g_variant_iter_loop (array, "&o", &str))
3092       g_assert_cmpstr (str, ==, test_strs[i++]);
3093     g_assert (i == 3);
3094
3095     g_variant_iter_free (array);
3096
3097     g_variant_iter_next (&tuple, "^a&o", &strv);
3098     g_variant_iter_next (&tuple, "^ao", &my_strv);
3099
3100     g_assert_cmpstr (strv[0], ==, "/hello");
3101     g_assert_cmpstr (strv[1], ==, "/world");
3102     g_assert (strv[2] == NULL);
3103     g_assert_cmpstr (my_strv[0], ==, "/hello");
3104     g_assert_cmpstr (my_strv[1], ==, "/world");
3105     g_assert (my_strv[2] == NULL);
3106
3107     g_variant_unref (value);
3108     g_strfreev (my_strv);
3109     g_free (strv);
3110   }
3111
3112   {
3113     const gchar *strvector[] = { "i", "ii", "iii", "iv", "v", "vi", NULL };
3114     GVariantBuilder builder;
3115     GVariantIter iter;
3116     GVariantIter *i2;
3117     GVariantIter *i3;
3118     GVariant *value;
3119     GVariant *sub;
3120     gchar **strv;
3121     gint i;
3122
3123     g_variant_builder_init (&builder, G_VARIANT_TYPE ("aas"));
3124     g_variant_builder_open (&builder, G_VARIANT_TYPE ("as"));
3125     for (i = 0; i < 6; i++)
3126       if (i & 1)
3127         g_variant_builder_add (&builder, "s", strvector[i]);
3128       else
3129         g_variant_builder_add (&builder, "&s", strvector[i]);
3130     g_variant_builder_close (&builder);
3131     g_variant_builder_add (&builder, "^as", strvector);
3132     g_variant_builder_add (&builder, "^as", strvector);
3133     value = g_variant_new ("aas", &builder);
3134
3135     g_variant_iter_init (&iter, value);
3136     while (g_variant_iter_loop (&iter, "^as", &strv))
3137       for (i = 0; i < 6; i++)
3138         g_assert_cmpstr (strv[i], ==, strvector[i]);
3139
3140     g_variant_iter_init (&iter, value);
3141     while (g_variant_iter_loop (&iter, "^a&s", &strv))
3142       for (i = 0; i < 6; i++)
3143         g_assert_cmpstr (strv[i], ==, strvector[i]);
3144
3145     g_variant_iter_init (&iter, value);
3146     while (g_variant_iter_loop (&iter, "as", &i2))
3147       {
3148         gchar *str;
3149
3150         i = 0;
3151         while (g_variant_iter_loop (i2, "s", &str))
3152           g_assert_cmpstr (str, ==, strvector[i++]);
3153         g_assert (i == 6);
3154       }
3155
3156     g_variant_iter_init (&iter, value);
3157     i3 = g_variant_iter_copy (&iter);
3158     while (g_variant_iter_loop (&iter, "@as", &sub))
3159       {
3160         gchar *str = g_variant_print (sub, TRUE);
3161         g_assert_cmpstr (str, ==,
3162                          "['i', 'ii', 'iii', 'iv', 'v', 'vi']");
3163         g_free (str);
3164       }
3165
3166     g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
3167                            "*NULL has already been returned*");
3168     g_variant_iter_next_value (&iter);
3169     g_test_assert_expected_messages ();
3170
3171     while (g_variant_iter_loop (i3, "*", &sub))
3172       {
3173         gchar *str = g_variant_print (sub, TRUE);
3174         g_assert_cmpstr (str, ==,
3175                          "['i', 'ii', 'iii', 'iv', 'v', 'vi']");
3176         g_free (str);
3177       }
3178
3179     g_variant_iter_free (i3);
3180
3181     for (i = 0; i < g_variant_n_children (value); i++)
3182       {
3183         gint j;
3184
3185         g_variant_get_child (value, i, "*", &sub);
3186
3187         for (j = 0; j < g_variant_n_children (sub); j++)
3188           {
3189             const gchar *str = NULL;
3190             GVariant *cval;
3191
3192             g_variant_get_child (sub, j, "&s", &str);
3193             g_assert_cmpstr (str, ==, strvector[j]);
3194
3195             cval = g_variant_get_child_value (sub, j);
3196             g_variant_get (cval, "&s", &str);
3197             g_assert_cmpstr (str, ==, strvector[j]);
3198             g_variant_unref (cval);
3199           }
3200
3201         g_variant_unref (sub);
3202       }
3203
3204     g_variant_unref (value);
3205   }
3206
3207   {
3208     gboolean justs[10];
3209     GVariant *value;
3210
3211     GVariant *vval;
3212     guchar byteval;
3213     gboolean bval;
3214     gint16 i16val;
3215     guint16 u16val;
3216     gint32 i32val;
3217     guint32 u32val;
3218     gint64 i64val;
3219     guint64 u64val;
3220     gdouble dval;
3221     gint32 hval;
3222
3223     /* test all 'nothing' */
3224     value = g_variant_new ("(mymbmnmqmimumxmtmhmdmv)",
3225                            FALSE, 'a',
3226                            FALSE, TRUE,
3227                            FALSE, (gint16) 123,
3228                            FALSE, (guint16) 123,
3229                            FALSE, (gint32) 123,
3230                            FALSE, (guint32) 123,
3231                            FALSE, (gint64) 123,
3232                            FALSE, (guint64) 123,
3233                            FALSE, (gint32) -1,
3234                            FALSE, (gdouble) 37.5,
3235                            NULL);
3236
3237     /* both NULL */
3238     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3239                    NULL, NULL,
3240                    NULL, NULL,
3241                    NULL, NULL,
3242                    NULL, NULL,
3243                    NULL, NULL,
3244                    NULL, NULL,
3245                    NULL, NULL,
3246                    NULL, NULL,
3247                    NULL, NULL,
3248                    NULL, NULL,
3249                    NULL);
3250
3251     /* NULL values */
3252     memset (justs, 1, sizeof justs);
3253     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3254                    &justs[0], NULL,
3255                    &justs[1], NULL,
3256                    &justs[2], NULL,
3257                    &justs[3], NULL,
3258                    &justs[4], NULL,
3259                    &justs[5], NULL,
3260                    &justs[6], NULL,
3261                    &justs[7], NULL,
3262                    &justs[8], NULL,
3263                    &justs[9], NULL,
3264                    NULL);
3265     g_assert (!(justs[0] || justs[1] || justs[2] || justs[3] || justs[4] ||
3266                 justs[5] || justs[6] || justs[7] || justs[8] || justs[9]));
3267
3268     /* both non-NULL */
3269     memset (justs, 1, sizeof justs);
3270     byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3271     vval = (void *) 1;
3272     bval = TRUE;
3273     dval = 88.88;
3274     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3275                    &justs[0], &byteval,
3276                    &justs[1], &bval,
3277                    &justs[2], &i16val,
3278                    &justs[3], &u16val,
3279                    &justs[4], &i32val,
3280                    &justs[5], &u32val,
3281                    &justs[6], &i64val,
3282                    &justs[7], &u64val,
3283                    &justs[8], &hval,
3284                    &justs[9], &dval,
3285                    &vval);
3286     g_assert (!(justs[0] || justs[1] || justs[2] || justs[3] || justs[4] ||
3287                 justs[5] || justs[6] || justs[7] || justs[8] || justs[9]));
3288     g_assert (byteval == '\0' && bval == FALSE);
3289     g_assert (i16val == 0 && u16val == 0 && i32val == 0 &&
3290               u32val == 0 && i64val == 0 && u64val == 0 &&
3291               hval == 0 && dval == 0.0);
3292     g_assert (vval == NULL);
3293
3294     /* NULL justs */
3295     byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3296     vval = (void *) 1;
3297     bval = TRUE;
3298     dval = 88.88;
3299     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3300                    NULL, &byteval,
3301                    NULL, &bval,
3302                    NULL, &i16val,
3303                    NULL, &u16val,
3304                    NULL, &i32val,
3305                    NULL, &u32val,
3306                    NULL, &i64val,
3307                    NULL, &u64val,
3308                    NULL, &hval,
3309                    NULL, &dval,
3310                    &vval);
3311     g_assert (byteval == '\0' && bval == FALSE);
3312     g_assert (i16val == 0 && u16val == 0 && i32val == 0 &&
3313               u32val == 0 && i64val == 0 && u64val == 0 &&
3314               hval == 0 && dval == 0.0);
3315     g_assert (vval == NULL);
3316
3317     g_variant_unref (value);
3318
3319
3320     /* test all 'just' */
3321     value = g_variant_new ("(mymbmnmqmimumxmtmhmdmv)",
3322                            TRUE, 'a',
3323                            TRUE, TRUE,
3324                            TRUE, (gint16) 123,
3325                            TRUE, (guint16) 123,
3326                            TRUE, (gint32) 123,
3327                            TRUE, (guint32) 123,
3328                            TRUE, (gint64) 123,
3329                            TRUE, (guint64) 123,
3330                            TRUE, (gint32) -1,
3331                            TRUE, (gdouble) 37.5,
3332                            g_variant_new ("()"));
3333
3334     /* both NULL */
3335     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3336                    NULL, NULL,
3337                    NULL, NULL,
3338                    NULL, NULL,
3339                    NULL, NULL,
3340                    NULL, NULL,
3341                    NULL, NULL,
3342                    NULL, NULL,
3343                    NULL, NULL,
3344                    NULL, NULL,
3345                    NULL, NULL,
3346                    NULL);
3347
3348     /* NULL values */
3349     memset (justs, 0, sizeof justs);
3350     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3351                    &justs[0], NULL,
3352                    &justs[1], NULL,
3353                    &justs[2], NULL,
3354                    &justs[3], NULL,
3355                    &justs[4], NULL,
3356                    &justs[5], NULL,
3357                    &justs[6], NULL,
3358                    &justs[7], NULL,
3359                    &justs[8], NULL,
3360                    &justs[9], NULL,
3361                    NULL);
3362     g_assert (justs[0] && justs[1] && justs[2] && justs[3] && justs[4] &&
3363               justs[5] && justs[6] && justs[7] && justs[8] && justs[9]);
3364
3365     /* both non-NULL */
3366     memset (justs, 0, sizeof justs);
3367     byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3368     vval = (void *) 1;
3369     bval = FALSE;
3370     dval = 88.88;
3371     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3372                    &justs[0], &byteval,
3373                    &justs[1], &bval,
3374                    &justs[2], &i16val,
3375                    &justs[3], &u16val,
3376                    &justs[4], &i32val,
3377                    &justs[5], &u32val,
3378                    &justs[6], &i64val,
3379                    &justs[7], &u64val,
3380                    &justs[8], &hval,
3381                    &justs[9], &dval,
3382                    &vval);
3383     g_assert (justs[0] && justs[1] && justs[2] && justs[3] && justs[4] &&
3384               justs[5] && justs[6] && justs[7] && justs[8] && justs[9]);
3385     g_assert (byteval == 'a' && bval == TRUE);
3386     g_assert (i16val == 123 && u16val == 123 && i32val == 123 &&
3387               u32val == 123 && i64val == 123 && u64val == 123 &&
3388               hval == -1 && dval == 37.5);
3389     g_assert (g_variant_is_of_type (vval, G_VARIANT_TYPE_UNIT));
3390     g_variant_unref (vval);
3391
3392     /* NULL justs */
3393     byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3394     vval = (void *) 1;
3395     bval = TRUE;
3396     dval = 88.88;
3397     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3398                    NULL, &byteval,
3399                    NULL, &bval,
3400                    NULL, &i16val,
3401                    NULL, &u16val,
3402                    NULL, &i32val,
3403                    NULL, &u32val,
3404                    NULL, &i64val,
3405                    NULL, &u64val,
3406                    NULL, &hval,
3407                    NULL, &dval,
3408                    &vval);
3409     g_assert (byteval == 'a' && bval == TRUE);
3410     g_assert (i16val == 123 && u16val == 123 && i32val == 123 &&
3411               u32val == 123 && i64val == 123 && u64val == 123 &&
3412               hval == -1 && dval == 37.5);
3413     g_assert (g_variant_is_of_type (vval, G_VARIANT_TYPE_UNIT));
3414     g_variant_unref (vval);
3415
3416     g_variant_unref (value);
3417   }
3418
3419   {
3420     GVariant *value;
3421     gchar *str;
3422
3423     value = g_variant_new ("(masas)", NULL, NULL);
3424     g_variant_ref_sink (value);
3425
3426     str = g_variant_print (value, TRUE);
3427     g_assert_cmpstr (str, ==, "(@mas nothing, @as [])");
3428     g_variant_unref (value);
3429     g_free (str);
3430
3431     do_failed_test ("/gvariant/varargs/subprocess/empty-array",
3432                     "*which type of empty array*");
3433   }
3434
3435   g_variant_type_info_assert_no_infos ();
3436 }
3437
3438 static void
3439 hash_get (GVariant    *value,
3440           const gchar *format,
3441           ...)
3442 {
3443   const gchar *endptr = NULL;
3444   gboolean hash;
3445   va_list ap;
3446
3447   hash = g_str_has_suffix (format, "#");
3448
3449   va_start (ap, format);
3450   g_variant_get_va (value, format, hash ? &endptr : NULL, &ap);
3451   va_end (ap);
3452
3453   if (hash)
3454     g_assert (*endptr == '#');
3455 }
3456
3457 static GVariant *
3458 hash_new (const gchar *format,
3459           ...)
3460 {
3461   const gchar *endptr = NULL;
3462   GVariant *value;
3463   gboolean hash;
3464   va_list ap;
3465
3466   hash = g_str_has_suffix (format, "#");
3467
3468   va_start (ap, format);
3469   value = g_variant_new_va (format, hash ? &endptr : NULL, &ap);
3470   va_end (ap);
3471
3472   if (hash)
3473     g_assert (*endptr == '#');
3474
3475   return value;
3476 }
3477
3478 static void
3479 test_valist (void)
3480 {
3481   GVariant *value;
3482   gint32 x;
3483
3484   x = 0;
3485   value = hash_new ("i", 234);
3486   hash_get (value, "i", &x);
3487   g_assert (x == 234);
3488   g_variant_unref (value);
3489
3490   x = 0;
3491   value = hash_new ("i#", 234);
3492   hash_get (value, "i#", &x);
3493   g_assert (x == 234);
3494   g_variant_unref (value);
3495
3496   g_variant_type_info_assert_no_infos ();
3497 }
3498
3499 static void
3500 test_builder_memory (void)
3501 {
3502   GVariantBuilder *hb;
3503   GVariantBuilder sb;
3504
3505   hb = g_variant_builder_new  (G_VARIANT_TYPE_ARRAY);
3506   g_variant_builder_open (hb, G_VARIANT_TYPE_ARRAY);
3507   g_variant_builder_open (hb, G_VARIANT_TYPE_ARRAY);
3508   g_variant_builder_open (hb, G_VARIANT_TYPE_ARRAY);
3509   g_variant_builder_add (hb, "s", "some value");
3510   g_variant_builder_ref (hb);
3511   g_variant_builder_unref (hb);
3512   g_variant_builder_unref (hb);
3513
3514   hb = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
3515   g_variant_builder_unref (hb);
3516
3517   hb = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
3518   g_variant_builder_clear (hb);
3519   g_variant_builder_unref (hb);
3520
3521   g_variant_builder_init (&sb, G_VARIANT_TYPE_ARRAY);
3522   g_variant_builder_open (&sb, G_VARIANT_TYPE_ARRAY);
3523   g_variant_builder_open (&sb, G_VARIANT_TYPE_ARRAY);
3524   g_variant_builder_add (&sb, "s", "some value");
3525   g_variant_builder_clear (&sb);
3526
3527   g_variant_type_info_assert_no_infos ();
3528 }
3529
3530 static void
3531 test_hashing (void)
3532 {
3533   GVariant *items[4096];
3534   GHashTable *table;
3535   gint i;
3536
3537   table = g_hash_table_new_full (g_variant_hash, g_variant_equal,
3538                                  (GDestroyNotify ) g_variant_unref,
3539                                  NULL);
3540
3541   for (i = 0; i < G_N_ELEMENTS (items); i++)
3542     {
3543       TreeInstance *tree;
3544       gint j;
3545
3546  again:
3547       tree = tree_instance_new (NULL, 0);
3548       items[i] = tree_instance_get_gvariant (tree);
3549       tree_instance_free (tree);
3550
3551       for (j = 0; j < i; j++)
3552         if (g_variant_equal (items[i], items[j]))
3553           {
3554             g_variant_unref (items[i]);
3555             goto again;
3556           }
3557
3558       g_hash_table_insert (table,
3559                            g_variant_ref_sink (items[i]),
3560                            GINT_TO_POINTER (i));
3561     }
3562
3563   for (i = 0; i < G_N_ELEMENTS (items); i++)
3564     {
3565       gpointer result;
3566
3567       result = g_hash_table_lookup (table, items[i]);
3568       g_assert_cmpint (GPOINTER_TO_INT (result), ==, i);
3569     }
3570
3571   g_hash_table_unref (table);
3572
3573   g_variant_type_info_assert_no_infos ();
3574 }
3575
3576 static void
3577 test_gv_byteswap (void)
3578 {
3579 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
3580 # define native16(x)  x, 0
3581 # define swapped16(x) 0, x
3582 #else
3583 # define native16(x)  0, x
3584 # define swapped16(x) x, 0
3585 #endif
3586   /* all kinds of of crazy randomised testing already performed on the
3587    * byteswapper in the /gvariant/serialiser/byteswap test and all kinds
3588    * of crazy randomised testing performed against the serialiser
3589    * normalisation functions in the /gvariant/serialiser/fuzz/ tests.
3590    *
3591    * just test a few simple cases here to make sure they each work
3592    */
3593   guchar validbytes[] = { 'a', '\0', swapped16(66), 2,
3594                           0,
3595                           'b', '\0', swapped16(77), 2,
3596                           5, 11 };
3597   guchar corruptbytes[] = { 'a', '\0', swapped16(66), 2,
3598                             0,
3599                             'b', '\0', swapped16(77), 2,
3600                             6, 11 };
3601   guint valid_data[4], corrupt_data[4];
3602   GVariant *value, *swapped;
3603   gchar *string, *string2;
3604
3605   memcpy (valid_data, validbytes, sizeof validbytes);
3606   memcpy (corrupt_data, corruptbytes, sizeof corruptbytes);
3607
3608   /* trusted */
3609   value = g_variant_new_from_data (G_VARIANT_TYPE ("a(sn)"),
3610                                    valid_data, sizeof validbytes, TRUE,
3611                                    NULL, NULL);
3612   swapped = g_variant_byteswap (value);
3613   g_variant_unref (value);
3614   g_assert (g_variant_get_size (swapped) == 13);
3615   string = g_variant_print (swapped, FALSE);
3616   g_variant_unref (swapped);
3617   g_assert_cmpstr (string, ==, "[('a', 66), ('b', 77)]");
3618   g_free (string);
3619
3620   /* untrusted but valid */
3621   value = g_variant_new_from_data (G_VARIANT_TYPE ("a(sn)"),
3622                                    valid_data, sizeof validbytes, FALSE,
3623                                    NULL, NULL);
3624   swapped = g_variant_byteswap (value);
3625   g_variant_unref (value);
3626   g_assert (g_variant_get_size (swapped) == 13);
3627   string = g_variant_print (swapped, FALSE);
3628   g_variant_unref (swapped);
3629   g_assert_cmpstr (string, ==, "[('a', 66), ('b', 77)]");
3630   g_free (string);
3631
3632   /* untrusted, invalid */
3633   value = g_variant_new_from_data (G_VARIANT_TYPE ("a(sn)"),
3634                                    corrupt_data, sizeof corruptbytes, FALSE,
3635                                    NULL, NULL);
3636   string = g_variant_print (value, FALSE);
3637   swapped = g_variant_byteswap (value);
3638   g_variant_unref (value);
3639   g_assert (g_variant_get_size (swapped) == 13);
3640   value = g_variant_byteswap (swapped);
3641   g_variant_unref (swapped);
3642   string2 = g_variant_print (value, FALSE);
3643   g_assert (g_variant_get_size (value) == 13);
3644   g_variant_unref (value);
3645   g_assert_cmpstr (string, ==, string2);
3646   g_free (string2);
3647   g_free (string);
3648 }
3649
3650 static void
3651 test_parser (void)
3652 {
3653   TreeInstance *tree;
3654   GVariant *parsed;
3655   GVariant *value;
3656   gchar *pt, *p;
3657   gchar *res;
3658
3659   tree = tree_instance_new (NULL, 3);
3660   value = tree_instance_get_gvariant (tree);
3661   tree_instance_free (tree);
3662
3663   pt = g_variant_print (value, TRUE);
3664   p = g_variant_print (value, FALSE);
3665
3666   parsed = g_variant_parse (NULL, pt, NULL, NULL, NULL);
3667   res = g_variant_print (parsed, FALSE);
3668   g_assert_cmpstr (p, ==, res);
3669   g_variant_unref (parsed);
3670   g_free (res);
3671
3672   parsed = g_variant_parse (g_variant_get_type (value), p,
3673                             NULL, NULL, NULL);
3674   res = g_variant_print (parsed, TRUE);
3675   g_assert_cmpstr (pt, ==, res);
3676   g_variant_unref (parsed);
3677   g_free (res);
3678
3679   g_variant_unref (value);
3680   g_free (pt);
3681   g_free (p);
3682 }
3683
3684 static void
3685 test_parses (void)
3686 {
3687   gint i;
3688
3689   for (i = 0; i < 100; i++)
3690     {
3691       test_parser ();
3692     }
3693
3694   /* mini test */
3695   {
3696     GError *error = NULL;
3697     gchar str[128];
3698     GVariant *val;
3699     gchar *p, *p2;
3700
3701     for (i = 0; i < 127; i++)
3702       str[i] = i + 1;
3703     str[i] = 0;
3704
3705     val = g_variant_new_string (str);
3706     p = g_variant_print (val, FALSE);
3707     g_variant_unref (val);
3708
3709     val = g_variant_parse (NULL, p, NULL, NULL, &error);
3710     p2 = g_variant_print (val, FALSE);
3711
3712     g_assert_cmpstr (str, ==, g_variant_get_string (val, NULL));
3713     g_assert_cmpstr (p, ==, p2);
3714
3715     g_variant_unref (val);
3716     g_free (p2);
3717     g_free (p);
3718   }
3719
3720   /* another mini test */
3721   {
3722     const gchar *end;
3723     GVariant *value;
3724
3725     value = g_variant_parse (G_VARIANT_TYPE_INT32, "1 2 3", NULL, &end, NULL);
3726     g_assert_cmpint (g_variant_get_int32 (value), ==, 1);
3727     /* make sure endptr returning works */
3728     g_assert_cmpstr (end, ==, " 2 3");
3729     g_variant_unref (value);
3730   }
3731
3732   /* unicode mini test */
3733   {
3734     /* ał𝄞 */
3735     const gchar orig[] = "a\xc5\x82\xf0\x9d\x84\x9e \t\n";
3736     GVariant *value;
3737     gchar *printed;
3738
3739     value = g_variant_new_string (orig);
3740     printed = g_variant_print (value, FALSE);
3741     g_variant_unref (value);
3742
3743     g_assert_cmpstr (printed, ==, "'a\xc5\x82\xf0\x9d\x84\x9e \\t\\n'");
3744     value = g_variant_parse (NULL, printed, NULL, NULL, NULL);
3745     g_assert_cmpstr (g_variant_get_string (value, NULL), ==, orig);
3746     g_variant_unref (value);
3747     g_free (printed);
3748   }
3749
3750   /* escapes */
3751   {
3752     const gchar orig[] = " \342\200\254 \360\220\210\240 \a \b \f \n \r \t \v ";
3753     GVariant *value;
3754     gchar *printed;
3755
3756     value = g_variant_new_string (orig);
3757     printed = g_variant_print (value, FALSE);
3758     g_variant_unref (value);
3759
3760     g_assert_cmpstr (printed, ==, "' \\u202c \\U00010220 \\a \\b \\f \\n \\r \\t \\v '");
3761     value = g_variant_parse (NULL, printed, NULL, NULL, NULL);
3762     g_assert_cmpstr (g_variant_get_string (value, NULL), ==, orig);
3763     g_variant_unref (value);
3764     g_free (printed);
3765   }
3766
3767 #ifndef _MSC_VER
3768   /* inf/nan strings are C99 features which Visual C++ does not support */
3769   /* inf/nan mini test */
3770   {
3771     const gchar *tests[] = { "inf", "-inf", "nan" };
3772     GVariant *value;
3773     gchar *printed;
3774     gchar *printed_down;
3775     gint i;
3776
3777     for (i = 0; i < G_N_ELEMENTS (tests); i++)
3778       {
3779         GError *error = NULL;
3780         value = g_variant_parse (NULL, tests[i], NULL, NULL, &error);
3781         printed = g_variant_print (value, FALSE);
3782         /* Canonicalize to lowercase; https://bugzilla.gnome.org/show_bug.cgi?id=704585 */
3783         printed_down = g_ascii_strdown (printed, -1);
3784         g_assert (g_str_has_prefix (printed_down, tests[i]));
3785         g_free (printed);
3786         g_free (printed_down);
3787         g_variant_unref (value);
3788       }
3789   }
3790 #endif
3791
3792   g_variant_type_info_assert_no_infos ();
3793 }
3794
3795 static void
3796 test_parse_failures (void)
3797 {
3798   const gchar *test[] = {
3799     "[1, 2,",                   "6:",              "expected value",
3800     "",                         "0:",              "expected value",
3801     "(1, 2,",                   "6:",              "expected value",
3802     "<1",                       "2:",              "expected '>'",
3803     "[]",                       "0-2:",            "unable to infer",
3804     "(,",                       "1:",              "expected value",
3805     "[4,'']",                   "1-2,3-5:",        "common type",
3806     "[4, '', 5]",               "1-2,4-6:",        "common type",
3807     "['', 4, 5]",               "1-3,5-6:",        "common type",
3808     "[4, 5, '']",               "1-2,7-9:",        "common type",
3809     "[[4], [], ['']]",          "1-4,10-14:",      "common type",
3810     "[[], [4], ['']]",          "5-8,10-14:",      "common type",
3811     "just",                     "4:",              "expected value",
3812     "nothing",                  "0-7:",            "unable to infer",
3813     "just [4, '']",             "6-7,9-11:",       "common type",
3814     "[[4,'']]",                 "2-3,4-6:",        "common type",
3815     "([4,''],)",                "2-3,4-6:",        "common type",
3816     "(4)",                      "2:",              "','",
3817     "{}",                       "0-2:",            "unable to infer",
3818     "{[1,2],[3,4]}",            "0-13:",           "basic types",
3819     "{[1,2]:[3,4]}",            "0-13:",           "basic types",
3820     "justt",                    "0-5:",            "unknown keyword",
3821     "nothng",                   "0-6:",            "unknown keyword",
3822     "uint33",                   "0-6:",            "unknown keyword",
3823     "@mi just ''",              "9-11:",           "can not parse as",
3824     "@ai ['']",                 "5-7:",            "can not parse as",
3825     "@(i) ('',)",               "6-8:",            "can not parse as",
3826     "[[], 5]",                  "1-3,5-6:",        "common type",
3827     "[[5], 5]",                 "1-4,6-7:",        "common type",
3828     "5 5",                      "2:",              "expected end of input",
3829     "[5, [5, '']]",             "5-6,8-10:",       "common type",
3830     "@i just 5",                "3-9:",            "can not parse as",
3831     "@i nothing",               "3-10:",           "can not parse as",
3832     "@i []",                    "3-5:",            "can not parse as",
3833     "@i ()",                    "3-5:",            "can not parse as",
3834     "@ai (4,)",                 "4-8:",            "can not parse as",
3835     "@(i) []",                  "5-7:",            "can not parse as",
3836     "(5 5)",                    "3:",              "expected ','",
3837     "[5 5]",                    "3:",              "expected ',' or ']'",
3838     "(5, 5 5)",                 "6:",              "expected ',' or ')'",
3839     "[5, 5 5]",                 "6:",              "expected ',' or ']'",
3840     "<@i []>",                  "4-6:",            "can not parse as",
3841     "<[5 5]>",                  "4:",              "expected ',' or ']'",
3842     "{[4,''],5}",               "2-3,4-6:",        "common type",
3843     "{5,[4,'']}",               "4-5,6-8:",        "common type",
3844     "@i {1,2}",                 "3-8:",            "can not parse as",
3845     "{@i '', 5}",               "4-6:",            "can not parse as",
3846     "{5, @i ''}",               "7-9:",            "can not parse as",
3847     "@ai {}",                   "4-6:",            "can not parse as",
3848     "{@i '': 5}",               "4-6:",            "can not parse as",
3849     "{5: @i ''}",               "7-9:",            "can not parse as",
3850     "{<4,5}",                   "3:",              "expected '>'",
3851     "{4,<5}",                   "5:",              "expected '>'",
3852     "{4,5,6}",                  "4:",              "expected '}'",
3853     "{5 5}",                    "3:",              "expected ':' or ','",
3854     "{4: 5: 6}",                "5:",              "expected ',' or '}'",
3855     "{4:5,<6:7}",               "7:",              "expected '>'",
3856     "{4:5,6:<7}",               "9:",              "expected '>'",
3857     "{4:5,6 7}",                "7:",              "expected ':'",
3858     "@o 'foo'",                 "3-8:",            "object path",
3859     "@g 'zzz'",                 "3-8:",            "signature",
3860     "@i true",                  "3-7:",            "can not parse as",
3861     "@z 4",                     "0-2:",            "invalid type",
3862     "@a* []",                   "0-3:",            "definite",
3863     "@ai [3 3]",                "7:",              "expected ',' or ']'",
3864     "18446744073709551616",     "0-20:",           "too big for any type",
3865     "-18446744073709551616",    "0-21:",           "too big for any type",
3866     "byte 256",                 "5-8:",            "out of range for type",
3867     "byte -1",                  "5-7:",            "out of range for type",
3868     "int16 32768",              "6-11:",           "out of range for type",
3869     "int16 -32769",             "6-12:",           "out of range for type",
3870     "uint16 -1",                "7-9:",            "out of range for type",
3871     "uint16 65536",             "7-12:",           "out of range for type",
3872     "2147483648",               "0-10:",           "out of range for type",
3873     "-2147483649",              "0-11:",           "out of range for type",
3874     "uint32 -1",                "7-9:",            "out of range for type",
3875     "uint32 4294967296",        "7-17:",           "out of range for type",
3876     "@x 9223372036854775808",   "3-22:",           "out of range for type",
3877     "@x -9223372036854775809",  "3-23:",           "out of range for type",
3878     "@t -1",                    "3-5:",            "out of range for type",
3879     "@t 18446744073709551616",  "3-23:",           "too big for any type",
3880     "handle 2147483648",        "7-17:",           "out of range for type",
3881     "handle -2147483649",       "7-18:",           "out of range for type",
3882     "1.798e308",                "0-9:",            "too big for any type",
3883     "37.5a488",                 "4-5:",            "invalid character",
3884     "0x7ffgf",                  "5-6:",            "invalid character",
3885     "07758",                    "4-5:",            "invalid character",
3886     "123a5",                    "3-4:",            "invalid character",
3887     "@ai 123",                  "4-7:",            "can not parse as",
3888     "'\"\\'",                   "0-4:",            "unterminated string",
3889     "'\"\\'\\",                 "0-5:",            "unterminated string",
3890     "boolean 4",                "8-9:",            "can not parse as",
3891     "int32 true",               "6-10:",           "can not parse as",
3892     "[double 5, int32 5]",      "1-9,11-18:",      "common type",
3893     "string 4",                 "7-8:",            "can not parse as"
3894   };
3895   gint i;
3896
3897   for (i = 0; i < G_N_ELEMENTS (test); i += 3)
3898     {
3899       GError *error = NULL;
3900       GVariant *value;
3901
3902       value = g_variant_parse (NULL, test[i], NULL, NULL, &error);
3903       g_assert (value == NULL);
3904
3905       if (!strstr (error->message, test[i+2]))
3906         g_error ("test %d: Can't find '%s' in '%s'", i / 3,
3907                  test[i+2], error->message);
3908
3909       if (!g_str_has_prefix (error->message, test[i+1]))
3910         g_error ("test %d: Expected location '%s' in '%s'", i / 3,
3911                  test[i+1], error->message);
3912
3913       g_error_free (error);
3914     }
3915 }
3916
3917 static void
3918 test_parse_bad_format_char (void)
3919 {
3920   g_variant_new_parsed ("%z");
3921
3922   g_assert_not_reached ();
3923 }
3924
3925 static void
3926 test_parse_bad_format_string (void)
3927 {
3928   g_variant_new_parsed ("uint32 %i", 2);
3929
3930   g_assert_not_reached ();
3931 }
3932
3933 static void
3934 test_parse_bad_args (void)
3935 {
3936   g_variant_new_parsed ("%@i", g_variant_new_uint32 (2));
3937
3938   g_assert_not_reached ();
3939 }
3940
3941 static void
3942 test_parse_positional (void)
3943 {
3944   GVariant *value;
3945   check_and_free (g_variant_new_parsed ("[('one', 1), (%s, 2),"
3946                                         " ('three', %i)]", "two", 3),
3947                   "[('one', 1), ('two', 2), ('three', 3)]");
3948   value = g_variant_new_parsed ("[('one', 1), (%s, 2),"
3949                                 " ('three', %u)]", "two", 3);
3950   g_assert (g_variant_is_of_type (value, G_VARIANT_TYPE ("a(su)")));
3951   check_and_free (value, "[('one', 1), ('two', 2), ('three', 3)]");
3952   check_and_free (g_variant_new_parsed ("{%s:%i}", "one", 1), "{'one': 1}");
3953
3954   if (g_test_undefined ())
3955     {
3956       do_failed_test ("/gvariant/parse/subprocess/bad-format-char",
3957                       "*GVariant format string*");
3958
3959       do_failed_test ("/gvariant/parse/subprocess/bad-format-string",
3960                       "*can not parse as*");
3961
3962       do_failed_test ("/gvariant/parse/subprocess/bad-args",
3963                       "*expected GVariant of type 'i'*");
3964     }
3965 }
3966
3967 static void
3968 test_floating (void)
3969 {
3970   GVariant *value;
3971
3972   value = g_variant_new_int32 (42);
3973   g_assert (g_variant_is_floating (value));
3974   g_variant_ref_sink (value);
3975   g_assert (!g_variant_is_floating (value));
3976   g_variant_unref (value);
3977 }
3978
3979 static void
3980 test_bytestring (void)
3981 {
3982   const gchar *test_string = "foo,bar,baz,quux,\xffoooo";
3983   GVariant *value;
3984   gchar **strv;
3985   gchar *str;
3986   const gchar *const_str;
3987   GVariant *untrusted_empty;
3988
3989   strv = g_strsplit (test_string, ",", 0);
3990
3991   value = g_variant_new_bytestring_array ((const gchar **) strv, -1);
3992   g_assert (g_variant_is_floating (value));
3993   g_strfreev (strv);
3994
3995   str = g_variant_print (value, FALSE);
3996   g_variant_unref (value);
3997
3998   value = g_variant_parse (NULL, str, NULL, NULL, NULL);
3999   g_free (str);
4000
4001   strv = g_variant_dup_bytestring_array (value, NULL);
4002   g_variant_unref (value);
4003
4004   str = g_strjoinv (",", strv);
4005   g_strfreev (strv);
4006
4007   g_assert_cmpstr (str, ==, test_string);
4008   g_free (str);
4009
4010   strv = g_strsplit (test_string, ",", 0);
4011   value = g_variant_new ("(^aay^a&ay^ay^&ay)",
4012                          strv, strv, strv[0], strv[0]);
4013   g_strfreev (strv);
4014
4015   g_variant_get_child (value, 0, "^a&ay", &strv);
4016   str = g_strjoinv (",", strv);
4017   g_free (strv);
4018   g_assert_cmpstr (str, ==, test_string);
4019   g_free (str);
4020
4021   g_variant_get_child (value, 0, "^aay", &strv);
4022   str = g_strjoinv (",", strv);
4023   g_strfreev (strv);
4024   g_assert_cmpstr (str, ==, test_string);
4025   g_free (str);
4026
4027   g_variant_get_child (value, 1, "^a&ay", &strv);
4028   str = g_strjoinv (",", strv);
4029   g_free (strv);
4030   g_assert_cmpstr (str, ==, test_string);
4031   g_free (str);
4032
4033   g_variant_get_child (value, 1, "^aay", &strv);
4034   str = g_strjoinv (",", strv);
4035   g_strfreev (strv);
4036   g_assert_cmpstr (str, ==, test_string);
4037   g_free (str);
4038
4039   g_variant_get_child (value, 2, "^ay", &str);
4040   g_assert_cmpstr (str, ==, "foo");
4041   g_free (str);
4042
4043   g_variant_get_child (value, 2, "^&ay", &str);
4044   g_assert_cmpstr (str, ==, "foo");
4045
4046   g_variant_get_child (value, 3, "^ay", &str);
4047   g_assert_cmpstr (str, ==, "foo");
4048   g_free (str);
4049
4050   g_variant_get_child (value, 3, "^&ay", &str);
4051   g_assert_cmpstr (str, ==, "foo");
4052   g_variant_unref (value);
4053
4054   untrusted_empty = g_variant_new_from_data (G_VARIANT_TYPE ("ay"), NULL, 0, FALSE, NULL, NULL);
4055   value = g_variant_get_normal_form (untrusted_empty);
4056   const_str = g_variant_get_bytestring (value);
4057   (void) const_str;
4058   g_variant_unref (value);
4059   g_variant_unref (untrusted_empty);
4060 }
4061
4062 static void
4063 test_lookup_value (void)
4064 {
4065   struct {
4066     const gchar *dict, *key, *value;
4067   } cases[] = {
4068     { "@a{ss} {'x':  'y'}",   "x",  "'y'" },
4069     { "@a{ss} {'x':  'y'}",   "y"         },
4070     { "@a{os} {'/x': 'y'}",   "/x", "'y'" },
4071     { "@a{os} {'/x': 'y'}",   "/y"        },
4072     { "@a{sv} {'x':  <'y'>}", "x",  "'y'" },
4073     { "@a{sv} {'x':  <5>}",   "x",  "5"   },
4074     { "@a{sv} {'x':  <'y'>}", "y"         }
4075   };
4076   gint i;
4077
4078   for (i = 0; i < G_N_ELEMENTS (cases); i++)
4079     {
4080       GVariant *dictionary;
4081       GVariant *value;
4082       gchar *p;
4083       
4084       dictionary = g_variant_parse (NULL, cases[i].dict, NULL, NULL, NULL);
4085       value = g_variant_lookup_value (dictionary, cases[i].key, NULL);
4086       g_variant_unref (dictionary);
4087
4088       if (value == NULL && cases[i].value == NULL)
4089         continue;
4090
4091       g_assert (value && cases[i].value);
4092       p = g_variant_print (value, FALSE);
4093       g_assert_cmpstr (cases[i].value, ==, p);
4094       g_variant_unref (value);
4095       g_free (p);
4096     }
4097 }
4098
4099 static void
4100 test_lookup (void)
4101 {
4102   const gchar *str;
4103   GVariant *dict;
4104   gboolean ok;
4105   gint num;
4106
4107   dict = g_variant_parse (NULL,
4108                           "{'a': <5>, 'b': <'c'>}",
4109                           NULL, NULL, NULL);
4110
4111   ok = g_variant_lookup (dict, "a", "i", &num);
4112   g_assert (ok);
4113   g_assert_cmpint (num, ==, 5);
4114
4115   ok = g_variant_lookup (dict, "a", "&s", &str);
4116   g_assert (!ok);
4117
4118   ok = g_variant_lookup (dict, "q", "&s", &str);
4119   g_assert (!ok);
4120
4121   ok = g_variant_lookup (dict, "b", "i", &num);
4122   g_assert (!ok);
4123
4124   ok = g_variant_lookup (dict, "b", "&s", &str);
4125   g_assert (ok);
4126   g_assert_cmpstr (str, ==, "c");
4127
4128   ok = g_variant_lookup (dict, "q", "&s", &str);
4129   g_assert (!ok);
4130
4131   g_variant_unref (dict);
4132 }
4133
4134 static GVariant *
4135 untrusted (GVariant *a)
4136 {
4137   GVariant *b;
4138   const GVariantType *type;
4139   GBytes *bytes;
4140
4141   type = g_variant_get_type (a);
4142   bytes = g_variant_get_data_as_bytes (a);
4143   b = g_variant_new_from_bytes (type, bytes, FALSE);
4144   g_bytes_unref (bytes);
4145   g_variant_unref (a);
4146
4147   return b;
4148 }
4149
4150 static void
4151 test_compare (void)
4152 {
4153   GVariant *a;
4154   GVariant *b;
4155
4156   a = untrusted (g_variant_new_byte (5));
4157   b = g_variant_new_byte (6);
4158   g_assert (g_variant_compare (a, b) < 0);
4159   g_variant_unref (a);
4160   g_variant_unref (b);
4161   a = untrusted (g_variant_new_int16 (G_MININT16));
4162   b = g_variant_new_int16 (G_MAXINT16);
4163   g_assert (g_variant_compare (a, b) < 0);
4164   g_variant_unref (a);
4165   g_variant_unref (b);
4166   a = untrusted (g_variant_new_uint16 (0));
4167   b = g_variant_new_uint16 (G_MAXUINT16);
4168   g_assert (g_variant_compare (a, b) < 0);
4169   g_variant_unref (a);
4170   g_variant_unref (b);
4171   a = untrusted (g_variant_new_int32 (G_MININT32));
4172   b = g_variant_new_int32 (G_MAXINT32);
4173   g_assert (g_variant_compare (a, b) < 0);
4174   g_variant_unref (a);
4175   g_variant_unref (b);
4176   a = untrusted (g_variant_new_uint32 (0));
4177   b = g_variant_new_uint32 (G_MAXUINT32);
4178   g_assert (g_variant_compare (a, b) < 0);
4179   g_variant_unref (a);
4180   g_variant_unref (b);
4181   a = untrusted (g_variant_new_int64 (G_MININT64));
4182   b = g_variant_new_int64 (G_MAXINT64);
4183   g_assert (g_variant_compare (a, b) < 0);
4184   g_variant_unref (a);
4185   g_variant_unref (b);
4186   a = untrusted (g_variant_new_uint64 (0));
4187   b = g_variant_new_uint64 (G_MAXUINT64);
4188   g_assert (g_variant_compare (a, b) < 0);
4189   g_variant_unref (a);
4190   g_variant_unref (b);
4191   a = untrusted (g_variant_new_double (G_MINDOUBLE));
4192   b = g_variant_new_double (G_MAXDOUBLE);
4193   g_assert (g_variant_compare (a, b) < 0);
4194   g_variant_unref (a);
4195   g_variant_unref (b);
4196   a = untrusted (g_variant_new_string ("abc"));
4197   b = g_variant_new_string ("abd");
4198   g_assert (g_variant_compare (a, b) < 0);
4199   g_variant_unref (a);
4200   g_variant_unref (b);
4201   a = untrusted (g_variant_new_object_path ("/abc"));
4202   b = g_variant_new_object_path ("/abd");
4203   g_assert (g_variant_compare (a, b) < 0);
4204   g_variant_unref (a);
4205   g_variant_unref (b);
4206   a = untrusted (g_variant_new_signature ("g"));
4207   b = g_variant_new_signature ("o");
4208   g_assert (g_variant_compare (a, b) < 0);
4209   g_variant_unref (a);
4210   g_variant_unref (b);
4211   a = untrusted (g_variant_new_boolean (FALSE));
4212   b = g_variant_new_boolean (TRUE);
4213   g_assert (g_variant_compare (a, b) < 0);
4214   g_variant_unref (a);
4215   g_variant_unref (b);
4216 }
4217
4218 static void
4219 test_equal (void)
4220 {
4221   GVariant *a;
4222   GVariant *b;
4223
4224   a = untrusted (g_variant_new_byte (5));
4225   b = g_variant_get_normal_form (a);
4226   g_assert (g_variant_equal (a, b));
4227   g_variant_unref (a);
4228   g_variant_unref (b);
4229   a = untrusted (g_variant_new_int16 (G_MININT16));
4230   b = g_variant_get_normal_form (a);
4231   g_assert (g_variant_equal (a, b));
4232   g_variant_unref (a);
4233   g_variant_unref (b);
4234   a = untrusted (g_variant_new_uint16 (0));
4235   b = g_variant_get_normal_form (a);
4236   g_assert (g_variant_equal (a, b));
4237   g_variant_unref (a);
4238   g_variant_unref (b);
4239   a = untrusted (g_variant_new_int32 (G_MININT32));
4240   b = g_variant_get_normal_form (a);
4241   g_assert (g_variant_equal (a, b));
4242   g_variant_unref (a);
4243   g_variant_unref (b);
4244   a = untrusted (g_variant_new_uint32 (0));
4245   b = g_variant_get_normal_form (a);
4246   g_assert (g_variant_equal (a, b));
4247   g_variant_unref (a);
4248   g_variant_unref (b);
4249   a = untrusted (g_variant_new_int64 (G_MININT64));
4250   b = g_variant_get_normal_form (a);
4251   g_assert (g_variant_equal (a, b));
4252   g_variant_unref (a);
4253   g_variant_unref (b);
4254   a = untrusted (g_variant_new_uint64 (0));
4255   b = g_variant_get_normal_form (a);
4256   g_assert (g_variant_equal (a, b));
4257   g_variant_unref (a);
4258   g_variant_unref (b);
4259   a = untrusted (g_variant_new_double (G_MINDOUBLE));
4260   b = g_variant_get_normal_form (a);
4261   g_assert (g_variant_equal (a, b));
4262   g_variant_unref (a);
4263   g_variant_unref (b);
4264   a = untrusted (g_variant_new_string ("abc"));
4265   g_assert (g_variant_equal (a, a));
4266   b = g_variant_get_normal_form (a);
4267   g_assert (g_variant_equal (a, b));
4268   g_variant_unref (a);
4269   g_variant_unref (b);
4270   a = untrusted (g_variant_new_object_path ("/abc"));
4271   g_assert (g_variant_equal (a, a));
4272   b = g_variant_get_normal_form (a);
4273   a = untrusted (a);
4274   g_assert (g_variant_equal (a, b));
4275   g_variant_unref (a);
4276   g_variant_unref (b);
4277   a = untrusted (g_variant_new_signature ("g"));
4278   g_assert (g_variant_equal (a, a));
4279   b = g_variant_get_normal_form (a);
4280   a = untrusted (a);
4281   g_assert (g_variant_equal (a, b));
4282   g_variant_unref (a);
4283   g_variant_unref (b);
4284   a = untrusted (g_variant_new_boolean (FALSE));
4285   b = g_variant_get_normal_form (a);
4286   g_assert (g_variant_equal (a, b));
4287   g_variant_unref (a);
4288   g_variant_unref (b);
4289 }
4290
4291 static void
4292 test_fixed_array (void)
4293 {
4294   GVariant *a;
4295   gint32 values[5];
4296   const gint32 *elts;
4297   gsize n_elts;
4298   gint i;
4299
4300   n_elts = 0;
4301   a = g_variant_new_parsed ("[1,2,3,4,5]");
4302   elts = g_variant_get_fixed_array (a, &n_elts, sizeof (gint32));
4303   g_assert (n_elts == 5);
4304   for (i = 0; i < 5; i++)
4305     g_assert_cmpint (elts[i], ==, i + 1);
4306   g_variant_unref (a);
4307
4308   n_elts = 0;
4309   for (i = 0; i < 5; i++)
4310     values[i] = i + 1;
4311   a = g_variant_new_fixed_array (G_VARIANT_TYPE_INT32, values,
4312                                  G_N_ELEMENTS (values), sizeof (values[0]));
4313   g_assert_cmpstr (g_variant_get_type_string (a), ==, "ai");
4314   elts = g_variant_get_fixed_array (a, &n_elts, sizeof (gint32));
4315   g_assert (n_elts == 5);
4316   for (i = 0; i < 5; i++)
4317     g_assert_cmpint (elts[i], ==, i + 1);
4318   g_variant_unref (a);
4319 }
4320
4321 static void
4322 test_check_format_string (void)
4323 {
4324   GVariant *value;
4325
4326   value = g_variant_new ("(sas)", "foo", NULL);
4327   g_variant_ref_sink (value);
4328
4329   g_assert (g_variant_check_format_string (value, "(s*)", TRUE));
4330   g_assert (g_variant_check_format_string (value, "(s*)", FALSE));
4331   g_assert (!g_variant_check_format_string (value, "(u*)", TRUE));
4332   g_assert (!g_variant_check_format_string (value, "(u*)", FALSE));
4333
4334   g_assert (g_variant_check_format_string (value, "(&s*)", FALSE));
4335   g_test_expect_message ("GLib", G_LOG_LEVEL_CRITICAL, "*contains a '&' character*");
4336   g_assert (!g_variant_check_format_string (value, "(&s*)", TRUE));
4337   g_test_assert_expected_messages ();
4338
4339   g_assert (g_variant_check_format_string (value, "(s^as)", TRUE));
4340   g_assert (g_variant_check_format_string (value, "(s^as)", FALSE));
4341
4342   g_test_expect_message ("GLib", G_LOG_LEVEL_CRITICAL, "*contains a '&' character*");
4343   g_assert (!g_variant_check_format_string (value, "(s^a&s)", TRUE));
4344   g_test_assert_expected_messages ();
4345   g_assert (g_variant_check_format_string (value, "(s^a&s)", FALSE));
4346
4347   g_variant_unref (value);
4348
4349   /* Do it again with a type that will let us put a '&' after a '^' */
4350   value = g_variant_new ("(say)", "foo", NULL);
4351   g_variant_ref_sink (value);
4352
4353   g_assert (g_variant_check_format_string (value, "(s*)", TRUE));
4354   g_assert (g_variant_check_format_string (value, "(s*)", FALSE));
4355   g_assert (!g_variant_check_format_string (value, "(u*)", TRUE));
4356   g_assert (!g_variant_check_format_string (value, "(u*)", FALSE));
4357
4358   g_assert (g_variant_check_format_string (value, "(&s*)", FALSE));
4359   g_test_expect_message ("GLib", G_LOG_LEVEL_CRITICAL, "*contains a '&' character*");
4360   g_assert (!g_variant_check_format_string (value, "(&s*)", TRUE));
4361   g_test_assert_expected_messages ();
4362
4363   g_assert (g_variant_check_format_string (value, "(s^ay)", TRUE));
4364   g_assert (g_variant_check_format_string (value, "(s^ay)", FALSE));
4365
4366   g_test_expect_message ("GLib", G_LOG_LEVEL_CRITICAL, "*contains a '&' character*");
4367   g_assert (!g_variant_check_format_string (value, "(s^&ay)", TRUE));
4368   g_test_assert_expected_messages ();
4369   g_assert (g_variant_check_format_string (value, "(s^&ay)", FALSE));
4370
4371   g_assert (g_variant_check_format_string (value, "r", FALSE));
4372   g_assert (g_variant_check_format_string (value, "(?a?)", FALSE));
4373
4374   g_variant_unref (value);
4375 }
4376
4377 static void
4378 verify_gvariant_checksum (const gchar  *sha256,
4379                           GVariant     *v)
4380              
4381 {
4382   gchar *checksum;
4383   checksum = g_compute_checksum_for_data (G_CHECKSUM_SHA256,
4384                                           g_variant_get_data (v),
4385                                           g_variant_get_size (v));
4386   g_assert_cmpstr (sha256, ==, checksum);
4387   g_free (checksum);
4388 }
4389
4390 static void
4391 verify_gvariant_checksum_va (const gchar *sha256,
4392                              const gchar *fmt,
4393                              ...)
4394 {
4395   va_list args;
4396   GVariant *v;
4397
4398   va_start (args, fmt);
4399
4400   v = g_variant_new_va (fmt, NULL, &args);
4401   g_variant_ref_sink (v);
4402 #if G_BYTE_ORDER == G_BIG_ENDIAN
4403   {
4404     GVariant *byteswapped = g_variant_byteswap (v);
4405     g_variant_unref (v);
4406     v = byteswapped;
4407   }
4408 #endif
4409
4410   va_end (args);
4411
4412   verify_gvariant_checksum (sha256, v);
4413
4414   g_variant_unref (v);
4415 }
4416
4417 static void
4418 test_checksum_basic (void)
4419 {
4420   verify_gvariant_checksum_va ("e8a4b2ee7ede79a3afb332b5b6cc3d952a65fd8cffb897f5d18016577c33d7cc",
4421                                "u", 42);
4422   verify_gvariant_checksum_va ("c53e363c33b00cfce298229ee83856b8a98c2e6126cab13f65899f62473b0df5",
4423                                "s", "moocow");
4424   verify_gvariant_checksum_va ("2b4c342f5433ebe591a1da77e013d1b72475562d48578dca8b84bac6651c3cb9",
4425                                "y", 9);
4426   verify_gvariant_checksum_va ("12a3ae445661ce5dee78d0650d33362dec29c4f82af05e7e57fb595bbbacf0ca",
4427                                "t", G_MAXUINT64);
4428   verify_gvariant_checksum_va ("e25a59b24440eb6c833aa79c93b9840e6eab6966add0dacf31df7e9e7000f5b3",
4429                                "d", 3.14159);
4430   verify_gvariant_checksum_va ("4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a",
4431                                "b", TRUE);
4432   verify_gvariant_checksum_va ("ca2fd00fa001190744c15c317643ab092e7048ce086a243e2be9437c898de1bb",
4433                                "q", G_MAXUINT16);
4434 }
4435
4436 static void
4437 test_checksum_nested (void)
4438 {
4439   static const char* const strv[] = {"foo", "bar", "baz", NULL};
4440
4441   verify_gvariant_checksum_va ("31fbc92f08fddaca716188fe4b5d44ae122fc6306fd3c6925af53cfa47ea596d",
4442                                "(uu)", 41, 43);
4443   verify_gvariant_checksum_va ("01759d683cead856d1d386d59af0578841698a424a265345ad5413122f220de8",
4444                                "(su)", "moocow", 79);
4445   verify_gvariant_checksum_va ("52b3ae95f19b3e642ea1d01185aea14a09004c1d1712672644427403a8a0afe6",
4446                                "(qyst)", G_MAXUINT16, 9, "moocow", G_MAXUINT64);
4447   verify_gvariant_checksum_va ("6fc6f4524161c3ae0d316812d7088e3fcd372023edaea2d7821093be40ae1060",
4448                                "(@ay)", g_variant_new_bytestring ("\xFF\xFF\xFF"));
4449   verify_gvariant_checksum_va ("572aca386e1a983dd23bb6eb6e3dfa72eef9ca7c7744581aa800e18d7d9d0b0b",
4450                                "(^as)", strv);
4451   verify_gvariant_checksum_va ("4bddf6174c791bb44fc6a4106573031690064df34b741033a0122ed8dc05bcf3",
4452                                "(yvu)", 254, g_variant_new ("(^as)", strv), 42);
4453 }
4454
4455 static void
4456 test_gbytes (void)
4457 {
4458   GVariant *a;
4459   GVariant *tuple;
4460   GBytes *bytes;
4461   GBytes *bytes2;
4462   const guint8 values[5] = { 1, 2, 3, 4, 5 };
4463   const guint8 *elts;
4464   gsize n_elts;
4465   gint i;
4466
4467   bytes = g_bytes_new (&values, 5);
4468   a = g_variant_new_from_bytes (G_VARIANT_TYPE_BYTESTRING, bytes, TRUE);
4469   g_bytes_unref (bytes);
4470   n_elts = 0;
4471   elts = g_variant_get_fixed_array (a, &n_elts, sizeof (guint8));
4472   g_assert (n_elts == 5);
4473   for (i = 0; i < 5; i++)
4474     g_assert_cmpint (elts[i], ==, i + 1);
4475
4476   bytes2 = g_variant_get_data_as_bytes (a);
4477   g_variant_unref (a);
4478
4479   bytes = g_bytes_new (&values, 5);
4480   g_assert (g_bytes_equal (bytes, bytes2));
4481   g_bytes_unref (bytes);
4482   g_bytes_unref (bytes2);
4483
4484   tuple = g_variant_new_parsed ("['foo', 'bar']");
4485   bytes = g_variant_get_data_as_bytes (tuple); /* force serialisation */
4486   a = g_variant_get_child_value (tuple, 1);
4487   bytes2 = g_variant_get_data_as_bytes (a);
4488   g_assert (!g_bytes_equal (bytes, bytes2));
4489
4490   g_bytes_unref (bytes);
4491   g_bytes_unref (bytes2);
4492   g_variant_unref (a);
4493   g_variant_unref (tuple);
4494 }
4495
4496 typedef struct {
4497   const GVariantType *type;
4498   const gchar *in;
4499   const gchar *out;
4500 } ContextTest;
4501
4502 static void
4503 test_print_context (void)
4504 {
4505   ContextTest tests[] = {
4506     { NULL, "(1, 2, 3, 'abc", "          ^^^^" },
4507     { NULL, "[1, 2, 3, 'str']", " ^        ^^^^^" },
4508     { G_VARIANT_TYPE_UINT16, "{ 'abc':'def' }", "  ^^^^^^^^^^^^^^^" },
4509     { NULL, "<5", "    ^" },
4510     { NULL, "'ab\\ux'", "  ^^^^^^^" },
4511     { NULL, "'ab\\U00efx'", "  ^^^^^^^^^^^" }
4512   };
4513   GVariant *v;
4514   gchar *s;
4515   gint i;
4516   GError *error = NULL;
4517
4518   for (i = 0; i < G_N_ELEMENTS (tests); i++)
4519     {
4520       v = g_variant_parse (tests[i].type, tests[i].in, NULL, NULL, &error);
4521       g_assert_null (v);
4522       s = g_variant_parse_error_print_context (error, tests[i].in);
4523       g_assert (strstr (s, tests[i].out) != NULL);
4524       g_free (s);
4525       g_clear_error (&error);
4526     }
4527 }
4528
4529 static void
4530 test_error_quark (void)
4531 {
4532 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
4533   g_assert (g_variant_parser_get_error_quark () == g_variant_parse_error_quark ());
4534 G_GNUC_END_IGNORE_DEPRECATIONS
4535 }
4536
4537 int
4538 main (int argc, char **argv)
4539 {
4540   gint i;
4541
4542   g_test_init (&argc, &argv, NULL);
4543
4544   g_test_add_func ("/gvariant/type", test_gvarianttype);
4545   g_test_add_func ("/gvariant/typeinfo", test_gvarianttypeinfo);
4546   g_test_add_func ("/gvariant/serialiser/maybe", test_maybes);
4547   g_test_add_func ("/gvariant/serialiser/array", test_arrays);
4548   g_test_add_func ("/gvariant/serialiser/tuple", test_tuples);
4549   g_test_add_func ("/gvariant/serialiser/variant", test_variants);
4550   g_test_add_func ("/gvariant/serialiser/strings", test_strings);
4551   g_test_add_func ("/gvariant/serialiser/byteswap", test_byteswaps);
4552
4553   for (i = 1; i <= 20; i += 4)
4554     {
4555       char *testname;
4556
4557       testname = g_strdup_printf ("/gvariant/serialiser/fuzz/%d%%", i);
4558       g_test_add_data_func (testname, GINT_TO_POINTER (i),
4559                             (gpointer) test_fuzzes);
4560       g_free (testname);
4561     }
4562
4563   g_test_add_func ("/gvariant/string", test_string);
4564   g_test_add_func ("/gvariant/utf8", test_utf8);
4565   g_test_add_func ("/gvariant/containers", test_containers);
4566   g_test_add_func ("/gvariant/format-strings", test_format_strings);
4567   g_test_add_func ("/gvariant/invalid-varargs", test_invalid_varargs);
4568   g_test_add_func ("/gvariant/varargs", test_varargs);
4569   g_test_add_func ("/gvariant/varargs/subprocess/empty-array", test_varargs_empty_array);
4570   g_test_add_func ("/gvariant/valist", test_valist);
4571   g_test_add_func ("/gvariant/builder-memory", test_builder_memory);
4572   g_test_add_func ("/gvariant/hashing", test_hashing);
4573   g_test_add_func ("/gvariant/byteswap", test_gv_byteswap);
4574   g_test_add_func ("/gvariant/parser", test_parses);
4575   g_test_add_func ("/gvariant/parse-failures", test_parse_failures);
4576   g_test_add_func ("/gvariant/parse-positional", test_parse_positional);
4577   g_test_add_func ("/gvariant/parse/subprocess/bad-format-char", test_parse_bad_format_char);
4578   g_test_add_func ("/gvariant/parse/subprocess/bad-format-string", test_parse_bad_format_string);
4579   g_test_add_func ("/gvariant/parse/subprocess/bad-args", test_parse_bad_args);
4580   g_test_add_func ("/gvariant/floating", test_floating);
4581   g_test_add_func ("/gvariant/bytestring", test_bytestring);
4582   g_test_add_func ("/gvariant/lookup-value", test_lookup_value);
4583   g_test_add_func ("/gvariant/lookup", test_lookup);
4584   g_test_add_func ("/gvariant/compare", test_compare);
4585   g_test_add_func ("/gvariant/equal", test_equal);
4586   g_test_add_func ("/gvariant/fixed-array", test_fixed_array);
4587   g_test_add_func ("/gvariant/check-format-string", test_check_format_string);
4588
4589   g_test_add_func ("/gvariant/checksum-basic", test_checksum_basic);
4590   g_test_add_func ("/gvariant/checksum-nested", test_checksum_nested);
4591
4592   g_test_add_func ("/gvariant/gbytes", test_gbytes);
4593   g_test_add_func ("/gvariant/print-context", test_print_context);
4594   g_test_add_func ("/gvariant/error-quark", test_error_quark);
4595
4596   return g_test_run ();
4597 }