Imported Upstream version 2.58.0
[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.1 of the License, 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_cmpmem (one.data, one.size, two.data, two.size);
2228
2229   tree_instance_free (tree);
2230   g_free (one.data);
2231   g_free (two.data);
2232 }
2233
2234 static void
2235 test_byteswaps (void)
2236 {
2237   int i;
2238
2239   for (i = 0; i < 200; i++)
2240     test_byteswap ();
2241
2242   g_variant_type_info_assert_no_infos ();
2243 }
2244
2245 static void
2246 test_fuzz (gdouble *fuzziness)
2247 {
2248   GVariantSerialised serialised;
2249   TreeInstance *tree;
2250
2251   /* make an instance */
2252   tree = tree_instance_new (NULL, 3);
2253
2254   /* serialise it */
2255   serialise_tree (tree, &serialised);
2256
2257   g_assert (g_variant_serialised_is_normal (serialised));
2258   g_assert (check_tree (tree, serialised));
2259
2260   if (serialised.size)
2261     {
2262       gboolean fuzzed = FALSE;
2263       gboolean a, b;
2264
2265       while (!fuzzed)
2266         {
2267           gint i;
2268
2269           for (i = 0; i < serialised.size; i++)
2270             if (randomly (*fuzziness))
2271               {
2272                 serialised.data[i] += g_test_rand_int_range (1, 256);
2273                 fuzzed = TRUE;
2274               }
2275         }
2276
2277       /* at least one byte in the serialised data has changed.
2278        *
2279        * this means that at least one of the following is true:
2280        *
2281        *    - the serialised data now represents a different value:
2282        *        check_tree() will return FALSE
2283        *
2284        *    - the serialised data is in non-normal form:
2285        *        g_variant_serialiser_is_normal() will return FALSE
2286        *
2287        * we always do both checks to increase exposure of the serialiser
2288        * to corrupt data.
2289        */
2290       a = g_variant_serialised_is_normal (serialised);
2291       b = check_tree (tree, serialised);
2292
2293       g_assert (!a || !b);
2294     }
2295
2296   tree_instance_free (tree);
2297   g_free (serialised.data);
2298 }
2299
2300
2301 static void
2302 test_fuzzes (gpointer data)
2303 {
2304   gdouble fuzziness;
2305   int i;
2306
2307   fuzziness = GPOINTER_TO_INT (data) / 100.;
2308
2309   for (i = 0; i < 200; i++)
2310     test_fuzz (&fuzziness);
2311
2312   g_variant_type_info_assert_no_infos ();
2313 }
2314
2315 static GVariant *
2316 tree_instance_get_gvariant (TreeInstance *tree)
2317 {
2318   const GVariantType *type;
2319   GVariant *result;
2320
2321   type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
2322
2323   switch (g_variant_type_info_get_type_char (tree->info))
2324     {
2325     case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
2326       {
2327         const GVariantType *child_type;
2328         GVariant *child;
2329
2330         if (tree->n_children)
2331           child = tree_instance_get_gvariant (tree->children[0]);
2332         else
2333           child = NULL;
2334
2335         child_type = g_variant_type_element (type);
2336
2337         if (child != NULL && randomly (0.5))
2338           child_type = NULL;
2339
2340         result = g_variant_new_maybe (child_type, child);
2341       }
2342       break;
2343
2344     case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
2345       {
2346         const GVariantType *child_type;
2347         GVariant **children;
2348         gint i;
2349
2350         children = g_new (GVariant *, tree->n_children);
2351         for (i = 0; i < tree->n_children; i++)
2352           children[i] = tree_instance_get_gvariant (tree->children[i]);
2353
2354         child_type = g_variant_type_element (type);
2355
2356         if (i > 0 && randomly (0.5))
2357           child_type = NULL;
2358
2359         result = g_variant_new_array (child_type, children, tree->n_children);
2360         g_free (children);
2361       }
2362       break;
2363
2364     case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
2365       {
2366         GVariant **children;
2367         gint i;
2368
2369         children = g_new (GVariant *, tree->n_children);
2370         for (i = 0; i < tree->n_children; i++)
2371           children[i] = tree_instance_get_gvariant (tree->children[i]);
2372
2373         result = g_variant_new_tuple (children, tree->n_children);
2374         g_free (children);
2375       }
2376       break;
2377
2378     case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
2379       {
2380         GVariant *key, *val;
2381
2382         g_assert (tree->n_children == 2);
2383
2384         key = tree_instance_get_gvariant (tree->children[0]);
2385         val = tree_instance_get_gvariant (tree->children[1]);
2386
2387         result = g_variant_new_dict_entry (key, val);
2388       }
2389       break;
2390
2391     case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
2392       {
2393         GVariant *value;
2394
2395         g_assert (tree->n_children == 1);
2396
2397         value = tree_instance_get_gvariant (tree->children[0]);
2398         result = g_variant_new_variant (value);
2399       }
2400       break;
2401
2402     case 'b':
2403       result = g_variant_new_boolean (tree->data.integer > 0);
2404       break;
2405
2406     case 'y':
2407       result = g_variant_new_byte (tree->data.integer);
2408       break;
2409
2410     case 'n':
2411       result = g_variant_new_int16 (tree->data.integer);
2412       break;
2413
2414     case 'q':
2415       result = g_variant_new_uint16 (tree->data.integer);
2416       break;
2417
2418     case 'i':
2419       result = g_variant_new_int32 (tree->data.integer);
2420       break;
2421
2422     case 'u':
2423       result = g_variant_new_uint32 (tree->data.integer);
2424       break;
2425
2426     case 'x':
2427       result = g_variant_new_int64 (tree->data.integer);
2428       break;
2429
2430     case 't':
2431       result = g_variant_new_uint64 (tree->data.integer);
2432       break;
2433
2434     case 'h':
2435       result = g_variant_new_handle (tree->data.integer);
2436       break;
2437
2438     case 'd':
2439       result = g_variant_new_double (tree->data.floating);
2440       break;
2441
2442     case 's':
2443       result = g_variant_new_string (tree->data.string);
2444       break;
2445
2446     case 'o':
2447       result = g_variant_new_object_path (tree->data.string);
2448       break;
2449
2450     case 'g':
2451       result = g_variant_new_signature (tree->data.string);
2452       break;
2453
2454     default:
2455       g_assert_not_reached ();
2456     }
2457
2458   return result;
2459 }
2460
2461 static gboolean
2462 tree_instance_check_gvariant (TreeInstance *tree,
2463                               GVariant     *value)
2464 {
2465   const GVariantType *type;
2466
2467   type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
2468   g_assert (g_variant_is_of_type (value, type));
2469
2470   switch (g_variant_type_info_get_type_char (tree->info))
2471     {
2472     case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
2473       {
2474         GVariant *child;
2475         gboolean equal;
2476
2477         child = g_variant_get_maybe (value);
2478
2479         if (child != NULL && tree->n_children == 1)
2480           equal = tree_instance_check_gvariant (tree->children[0], child);
2481         else if (child == NULL && tree->n_children == 0)
2482           equal = TRUE;
2483         else
2484           equal = FALSE;
2485
2486         if (child != NULL)
2487           g_variant_unref (child);
2488
2489         return equal;
2490       }
2491       break;
2492
2493     case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
2494     case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
2495     case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
2496       {
2497         gsize i;
2498
2499         if (g_variant_n_children (value) != tree->n_children)
2500           return FALSE;
2501
2502         for (i = 0; i < tree->n_children; i++)
2503           {
2504             GVariant *child;
2505             gboolean equal;
2506
2507             child = g_variant_get_child_value (value, i);
2508             equal = tree_instance_check_gvariant (tree->children[i], child);
2509             g_variant_unref (child);
2510
2511             if (!equal)
2512               return FALSE;
2513           }
2514
2515         return TRUE;
2516       }
2517       break;
2518
2519     case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
2520       {
2521         const gchar *str1, *str2;
2522         GVariant *child;
2523         gboolean equal;
2524
2525         child = g_variant_get_variant (value);
2526         str1 = g_variant_get_type_string (child);
2527         str2 = g_variant_type_info_get_type_string (tree->children[0]->info);
2528         /* GVariant only keeps one copy of type strings around */
2529         equal = str1 == str2 &&
2530                 tree_instance_check_gvariant (tree->children[0], child);
2531
2532         g_variant_unref (child);
2533
2534         return equal;
2535       }
2536       break;
2537
2538     case 'b':
2539       return g_variant_get_boolean (value) == tree->data.integer;
2540
2541     case 'y':
2542       return g_variant_get_byte (value) == (guchar) tree->data.integer;
2543
2544     case 'n':
2545       return g_variant_get_int16 (value) == (gint16) tree->data.integer;
2546
2547     case 'q':
2548       return g_variant_get_uint16 (value) == (guint16) tree->data.integer;
2549
2550     case 'i':
2551       return g_variant_get_int32 (value) == (gint32) tree->data.integer;
2552
2553     case 'u':
2554       return g_variant_get_uint32 (value) == (guint32) tree->data.integer;
2555
2556     case 'x':
2557       return g_variant_get_int64 (value) == (gint64) tree->data.integer;
2558
2559     case 't':
2560       return g_variant_get_uint64 (value) == (guint64) tree->data.integer;
2561
2562     case 'h':
2563       return g_variant_get_handle (value) == (gint32) tree->data.integer;
2564
2565     case 'd':
2566       {
2567         gdouble floating = g_variant_get_double (value);
2568
2569         return memcmp (&floating, &tree->data.floating, sizeof floating) == 0;
2570       }
2571
2572     case 's':
2573     case 'o':
2574     case 'g':
2575       return strcmp (g_variant_get_string (value, NULL),
2576                      tree->data.string) == 0;
2577
2578     default:
2579       g_assert_not_reached ();
2580     }
2581 }
2582
2583 static void
2584 tree_instance_build_gvariant (TreeInstance    *tree,
2585                               GVariantBuilder *builder,
2586                               gboolean         guess_ok)
2587 {
2588   const GVariantType *type;
2589
2590   type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
2591
2592   if (g_variant_type_is_container (type))
2593     {
2594       gsize i;
2595
2596       /* force GVariantBuilder to guess the type half the time */
2597       if (guess_ok && randomly (0.5))
2598         {
2599           if (g_variant_type_is_array (type) && tree->n_children)
2600             type = G_VARIANT_TYPE_ARRAY;
2601
2602           if (g_variant_type_is_maybe (type) && tree->n_children)
2603             type = G_VARIANT_TYPE_MAYBE;
2604
2605           if (g_variant_type_is_tuple (type))
2606             type = G_VARIANT_TYPE_TUPLE;
2607
2608           if (g_variant_type_is_dict_entry (type))
2609             type = G_VARIANT_TYPE_DICT_ENTRY;
2610         }
2611       else
2612         guess_ok = FALSE;
2613
2614       g_variant_builder_open (builder, type);
2615
2616       for (i = 0; i < tree->n_children; i++)
2617         tree_instance_build_gvariant (tree->children[i], builder, guess_ok);
2618
2619       g_variant_builder_close (builder);
2620     }
2621   else
2622     g_variant_builder_add_value (builder, tree_instance_get_gvariant (tree));
2623 }
2624
2625
2626 static gboolean
2627 tree_instance_check_iter (TreeInstance *tree,
2628                           GVariantIter *iter)
2629 {
2630   GVariant *value;
2631
2632   value = g_variant_iter_next_value (iter);
2633
2634   if (g_variant_is_container (value))
2635     {
2636       gsize i;
2637
2638       iter = g_variant_iter_new (value);
2639       g_variant_unref (value);
2640
2641       if (g_variant_iter_n_children (iter) != tree->n_children)
2642         {
2643           g_variant_iter_free (iter);
2644           return FALSE;
2645         }
2646
2647       for (i = 0; i < tree->n_children; i++)
2648         if (!tree_instance_check_iter (tree->children[i], iter))
2649           {
2650             g_variant_iter_free (iter);
2651             return FALSE;
2652           }
2653
2654       g_assert (g_variant_iter_next_value (iter) == NULL);
2655       g_variant_iter_free (iter);
2656
2657       return TRUE;
2658     }
2659
2660   else
2661     {
2662       gboolean equal;
2663
2664       equal = tree_instance_check_gvariant (tree, value);
2665       g_variant_unref (value);
2666
2667       return equal;
2668     }
2669 }
2670
2671 static void
2672 test_container (void)
2673 {
2674   TreeInstance *tree;
2675   GVariant *value;
2676   gchar *s1, *s2;
2677
2678   tree = tree_instance_new (NULL, 3);
2679   value = g_variant_ref_sink (tree_instance_get_gvariant (tree));
2680
2681   s1 = g_variant_print (value, TRUE);
2682   g_assert (tree_instance_check_gvariant (tree, value));
2683
2684   g_variant_get_data (value);
2685
2686   s2 = g_variant_print (value, TRUE);
2687   g_assert (tree_instance_check_gvariant (tree, value));
2688
2689   g_assert_cmpstr (s1, ==, s2);
2690
2691   if (g_variant_is_container (value))
2692     {
2693       GVariantBuilder builder;
2694       GVariantIter iter;
2695       GVariant *built;
2696       GVariant *val;
2697       gchar *s3;
2698
2699       g_variant_builder_init (&builder, G_VARIANT_TYPE_VARIANT);
2700       tree_instance_build_gvariant (tree, &builder, TRUE);
2701       built = g_variant_builder_end (&builder);
2702       g_variant_ref_sink (built);
2703       g_variant_get_data (built);
2704       val = g_variant_get_variant (built);
2705
2706       s3 = g_variant_print (val, TRUE);
2707       g_assert_cmpstr (s1, ==, s3);
2708
2709       g_variant_iter_init (&iter, built);
2710       g_assert (tree_instance_check_iter (tree, &iter));
2711       g_assert (g_variant_iter_next_value (&iter) == NULL);
2712
2713       g_variant_unref (built);
2714       g_variant_unref (val);
2715       g_free (s3);
2716     }
2717
2718   tree_instance_free (tree);
2719   g_variant_unref (value);
2720   g_free (s2);
2721   g_free (s1);
2722 }
2723
2724 static void
2725 test_string (void)
2726 {
2727   /* Test some different methods of creating strings */
2728   GVariant *v;
2729
2730   v = g_variant_new_string ("foo");
2731   g_assert_cmpstr (g_variant_get_string (v, NULL), ==, "foo");
2732   g_variant_unref (v);
2733
2734
2735   v = g_variant_new_take_string (g_strdup ("foo"));
2736   g_assert_cmpstr (g_variant_get_string (v, NULL), ==, "foo");
2737   g_variant_unref (v);
2738
2739   v = g_variant_new_printf ("%s %d", "foo", 123);
2740   g_assert_cmpstr (g_variant_get_string (v, NULL), ==, "foo 123");
2741   g_variant_unref (v);
2742 }
2743
2744 static void
2745 test_utf8 (void)
2746 {
2747   const gchar invalid[] = "hello\xffworld";
2748   GVariant *value;
2749
2750   /* ensure that the test data is not valid utf8... */
2751   g_assert (!g_utf8_validate (invalid, -1, NULL));
2752
2753   /* load the data untrusted */
2754   value = g_variant_new_from_data (G_VARIANT_TYPE_STRING,
2755                                    invalid, sizeof invalid,
2756                                    FALSE, NULL, NULL);
2757
2758   /* ensure that the problem is caught and we get valid UTF-8 */
2759   g_assert (g_utf8_validate (g_variant_get_string (value, NULL), -1, NULL));
2760   g_variant_unref (value);
2761
2762
2763   /* now load it trusted */
2764   value = g_variant_new_from_data (G_VARIANT_TYPE_STRING,
2765                                    invalid, sizeof invalid,
2766                                    TRUE, NULL, NULL);
2767
2768   /* ensure we get the invalid data (ie: make sure that time wasn't
2769    * wasted on validating data that was marked as trusted)
2770    */
2771   g_assert (g_variant_get_string (value, NULL) == invalid);
2772   g_variant_unref (value);
2773 }
2774
2775 static void
2776 test_containers (void)
2777 {
2778   gint i;
2779
2780   for (i = 0; i < 100; i++)
2781     {
2782       test_container ();
2783     }
2784
2785   g_variant_type_info_assert_no_infos ();
2786 }
2787
2788 static void
2789 test_format_strings (void)
2790 {
2791   GVariantType *type;
2792   const gchar *end;
2793
2794   g_assert (g_variant_format_string_scan ("i", NULL, &end) && *end == '\0');
2795   g_assert (g_variant_format_string_scan ("@i", NULL, &end) && *end == '\0');
2796   g_assert (g_variant_format_string_scan ("@ii", NULL, &end) && *end == 'i');
2797   g_assert (g_variant_format_string_scan ("^a&s", NULL, &end) && *end == '\0');
2798   g_assert (g_variant_format_string_scan ("(^as)", NULL, &end) &&
2799             *end == '\0');
2800   g_assert (!g_variant_format_string_scan ("(^s)", NULL, &end));
2801   g_assert (!g_variant_format_string_scan ("(^a)", NULL, &end));
2802   g_assert (!g_variant_format_string_scan ("(z)", NULL, &end));
2803   g_assert (!g_variant_format_string_scan ("az", NULL, &end));
2804   g_assert (!g_variant_format_string_scan ("{**}", NULL, &end));
2805   g_assert (!g_variant_format_string_scan ("{@**}", NULL, &end));
2806   g_assert (g_variant_format_string_scan ("{@y*}", NULL, &end) &&
2807             *end == '\0');
2808   g_assert (g_variant_format_string_scan ("{yv}", NULL, &end) &&
2809             *end == '\0');
2810   g_assert (!g_variant_format_string_scan ("{&?v}", NULL, &end));
2811   g_assert (g_variant_format_string_scan ("{@?v}", NULL, &end) &&
2812             *end == '\0');
2813   g_assert (!g_variant_format_string_scan ("{&@sv}", NULL, &end));
2814   g_assert (!g_variant_format_string_scan ("{@&sv}", NULL, &end));
2815   g_assert (g_variant_format_string_scan ("{&sv}", NULL, &end) &&
2816             *end == '\0');
2817   g_assert (!g_variant_format_string_scan ("{vv}", NULL, &end));
2818   g_assert (!g_variant_format_string_scan ("{y}", NULL, &end));
2819   g_assert (!g_variant_format_string_scan ("{yyy}", NULL, &end));
2820   g_assert (!g_variant_format_string_scan ("{ya}", NULL, &end));
2821   g_assert (g_variant_format_string_scan ("&s", NULL, &end) && *end == '\0');
2822   g_assert (!g_variant_format_string_scan ("&as", NULL, &end));
2823   g_assert (!g_variant_format_string_scan ("@z", NULL, &end));
2824   g_assert (!g_variant_format_string_scan ("az", NULL, &end));
2825   g_assert (!g_variant_format_string_scan ("a&s", NULL, &end));
2826
2827   type = g_variant_format_string_scan_type ("mm(@xy^a&s*?@?)", NULL, &end);
2828   g_assert (type && *end == '\0');
2829   g_assert (g_variant_type_equal (type, G_VARIANT_TYPE ("mm(xyas*?\?)")));
2830   g_variant_type_free (type);
2831
2832   type = g_variant_format_string_scan_type ("mm(@xy^a&*?@?)", NULL, NULL);
2833   g_assert (type == NULL);
2834 }
2835
2836 static void
2837 do_failed_test (const char *test,
2838                 const gchar *pattern)
2839 {
2840   g_test_trap_subprocess (test, 1000000, 0);
2841   g_test_trap_assert_failed ();
2842   g_test_trap_assert_stderr (pattern);
2843 }
2844
2845 static void
2846 test_invalid_varargs (void)
2847 {
2848   GVariant *value;
2849   const gchar *end;
2850
2851   if (!g_test_undefined ())
2852     return;
2853
2854   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
2855                          "*GVariant format string*");
2856   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
2857                          "*valid_format_string*");
2858   value = g_variant_new ("z");
2859   g_test_assert_expected_messages ();
2860   g_assert (value == NULL);
2861
2862   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
2863                          "*valid GVariant format string as a prefix*");
2864   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
2865                          "*valid_format_string*");
2866   value = g_variant_new_va ("z", &end, NULL);
2867   g_test_assert_expected_messages ();
2868   g_assert (value == NULL);
2869
2870   value = g_variant_new ("y", 'a');
2871   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
2872                          "*type of 'q' but * has a type of 'y'*");
2873   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
2874                          "*valid_format_string*");
2875   g_variant_get (value, "q");
2876   g_test_assert_expected_messages ();
2877   g_variant_unref (value);
2878 }
2879
2880 static void
2881 check_and_free (GVariant    *value,
2882                 const gchar *str)
2883 {
2884   gchar *valstr = g_variant_print (value, FALSE);
2885   g_assert_cmpstr (str, ==, valstr);
2886   g_variant_unref (value);
2887   g_free (valstr);
2888 }
2889
2890 static void
2891 test_varargs_empty_array (void)
2892 {
2893   g_variant_new ("(a{s*})", NULL);
2894
2895   g_assert_not_reached ();
2896 }
2897
2898 static void
2899 test_varargs (void)
2900 {
2901   {
2902     GVariantBuilder array;
2903
2904     g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
2905     g_variant_builder_add_parsed (&array, "{'size', <(%i, %i)> }", 800, 600);
2906     g_variant_builder_add (&array, "{sv}", "title",
2907                            g_variant_new_string ("Test case"));
2908     g_variant_builder_add_value (&array,
2909       g_variant_new_dict_entry (g_variant_new_string ("temperature"),
2910                                 g_variant_new_variant (
2911                                   g_variant_new_double (37.5))));
2912     check_and_free (g_variant_new ("(ma{sv}m(a{sv})ma{sv}ii)",
2913                                    NULL, FALSE, NULL, &array, 7777, 8888),
2914                     "(nothing, nothing, {'size': <(800, 600)>, "
2915                                         "'title': <'Test case'>, "
2916                                         "'temperature': <37.5>}, "
2917                      "7777, 8888)");
2918
2919     check_and_free (g_variant_new ("(imimimmimmimmi)",
2920                                    123,
2921                                    FALSE, 321,
2922                                    TRUE, 123,
2923                                    FALSE, TRUE, 321,
2924                                    TRUE, FALSE, 321,
2925                                    TRUE, TRUE, 123),
2926                     "(123, nothing, 123, nothing, just nothing, 123)");
2927
2928     check_and_free (g_variant_new ("(ybnixd)",
2929                                    'a', 1, 22, 33, (guint64) 44, 5.5),
2930                     "(0x61, true, 22, 33, 44, 5.5)");
2931
2932     check_and_free (g_variant_new ("(@y?*rv)",
2933                                    g_variant_new ("y", 'a'),
2934                                    g_variant_new ("y", 'b'),
2935                                    g_variant_new ("y", 'c'),
2936                                    g_variant_new ("(y)", 'd'),
2937                                    g_variant_new ("y", 'e')),
2938                     "(0x61, 0x62, 0x63, (0x64,), <byte 0x65>)");
2939   }
2940
2941   {
2942     GVariantBuilder array;
2943     GVariantIter iter;
2944     GVariant *value;
2945     gchar *number;
2946     gboolean just;
2947     gint i, val;
2948
2949     g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
2950     for (i = 0; i < 100; i++)
2951       {
2952         number = g_strdup_printf ("%d", i);
2953         g_variant_builder_add (&array, "s", number);
2954         g_free (number);
2955       }
2956
2957     value = g_variant_builder_end (&array);
2958     g_variant_iter_init (&iter, value);
2959
2960     i = 0;
2961     while (g_variant_iter_loop (&iter, "s", &number))
2962       {
2963         gchar *check = g_strdup_printf ("%d", i++);
2964         g_assert_cmpstr (number, ==, check);
2965         g_free (check);
2966       }
2967     g_assert (number == NULL);
2968     g_assert (i == 100);
2969
2970     g_variant_unref (value);
2971
2972     g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
2973     for (i = 0; i < 100; i++)
2974       g_variant_builder_add (&array, "mi", i % 2 == 0, i);
2975     value = g_variant_builder_end (&array);
2976
2977     i = 0;
2978     g_variant_iter_init (&iter, value);
2979     while (g_variant_iter_loop (&iter, "mi", NULL, &val))
2980       g_assert (val == i++ || val == 0);
2981     g_assert (i == 100);
2982
2983     i = 0;
2984     g_variant_iter_init (&iter, value);
2985     while (g_variant_iter_loop (&iter, "mi", &just, &val))
2986       {
2987         gint this = i++;
2988
2989         if (this % 2 == 0)
2990           {
2991             g_assert (just);
2992             g_assert (val == this);
2993           }
2994         else
2995           {
2996             g_assert (!just);
2997             g_assert (val == 0);
2998           }
2999       }
3000     g_assert (i == 100);
3001
3002     g_variant_unref (value);
3003   }
3004
3005   {
3006     const gchar *strvector[] = {"/hello", "/world", NULL};
3007     const gchar *test_strs[] = {"/foo", "/bar", "/baz" };
3008     GVariantBuilder builder;
3009     GVariantIter *array;
3010     GVariantIter tuple;
3011     const gchar **strv;
3012     gchar **my_strv;
3013     GVariant *value;
3014     gchar *str;
3015     gint i;
3016
3017     g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
3018     g_variant_builder_add (&builder, "s", "/foo");
3019     g_variant_builder_add (&builder, "s", "/bar");
3020     g_variant_builder_add (&builder, "s", "/baz");
3021     value = g_variant_new("(as^as^a&s)", &builder, strvector, strvector);
3022     g_variant_iter_init (&tuple, value);
3023     g_variant_iter_next (&tuple, "as", &array);
3024
3025     i = 0;
3026     while (g_variant_iter_loop (array, "s", &str))
3027       g_assert_cmpstr (str, ==, test_strs[i++]);
3028     g_assert (i == 3);
3029
3030     g_variant_iter_free (array);
3031
3032     /* start over */
3033     g_variant_iter_init (&tuple, value);
3034     g_variant_iter_next (&tuple, "as", &array);
3035
3036     i = 0;
3037     while (g_variant_iter_loop (array, "&s", &str))
3038       g_assert_cmpstr (str, ==, test_strs[i++]);
3039     g_assert (i == 3);
3040
3041     g_variant_iter_free (array);
3042
3043     g_variant_iter_next (&tuple, "^a&s", &strv);
3044     g_variant_iter_next (&tuple, "^as", &my_strv);
3045
3046     g_assert_cmpstr (strv[0], ==, "/hello");
3047     g_assert_cmpstr (strv[1], ==, "/world");
3048     g_assert (strv[2] == NULL);
3049     g_assert_cmpstr (my_strv[0], ==, "/hello");
3050     g_assert_cmpstr (my_strv[1], ==, "/world");
3051     g_assert (my_strv[2] == NULL);
3052
3053     g_variant_unref (value);
3054     g_strfreev (my_strv);
3055     g_free (strv);
3056   }
3057
3058   {
3059     const gchar *strvector[] = {"/hello", "/world", NULL};
3060     const gchar *test_strs[] = {"/foo", "/bar", "/baz" };
3061     GVariantBuilder builder;
3062     GVariantIter *array;
3063     GVariantIter tuple;
3064     const gchar **strv;
3065     gchar **my_strv;
3066     GVariant *value;
3067     gchar *str;
3068     gint i;
3069
3070     g_variant_builder_init (&builder, G_VARIANT_TYPE_OBJECT_PATH_ARRAY);
3071     g_variant_builder_add (&builder, "o", "/foo");
3072     g_variant_builder_add (&builder, "o", "/bar");
3073     g_variant_builder_add (&builder, "o", "/baz");
3074     value = g_variant_new("(ao^ao^a&o)", &builder, strvector, strvector);
3075     g_variant_iter_init (&tuple, value);
3076     g_variant_iter_next (&tuple, "ao", &array);
3077
3078     i = 0;
3079     while (g_variant_iter_loop (array, "o", &str))
3080       g_assert_cmpstr (str, ==, test_strs[i++]);
3081     g_assert (i == 3);
3082
3083     g_variant_iter_free (array);
3084
3085     /* start over */
3086     g_variant_iter_init (&tuple, value);
3087     g_variant_iter_next (&tuple, "ao", &array);
3088
3089     i = 0;
3090     while (g_variant_iter_loop (array, "&o", &str))
3091       g_assert_cmpstr (str, ==, test_strs[i++]);
3092     g_assert (i == 3);
3093
3094     g_variant_iter_free (array);
3095
3096     g_variant_iter_next (&tuple, "^a&o", &strv);
3097     g_variant_iter_next (&tuple, "^ao", &my_strv);
3098
3099     g_assert_cmpstr (strv[0], ==, "/hello");
3100     g_assert_cmpstr (strv[1], ==, "/world");
3101     g_assert (strv[2] == NULL);
3102     g_assert_cmpstr (my_strv[0], ==, "/hello");
3103     g_assert_cmpstr (my_strv[1], ==, "/world");
3104     g_assert (my_strv[2] == NULL);
3105
3106     g_variant_unref (value);
3107     g_strfreev (my_strv);
3108     g_free (strv);
3109   }
3110
3111   {
3112     const gchar *strvector[] = { "i", "ii", "iii", "iv", "v", "vi", NULL };
3113     GVariantBuilder builder;
3114     GVariantIter iter;
3115     GVariantIter *i2;
3116     GVariantIter *i3;
3117     GVariant *value;
3118     GVariant *sub;
3119     gchar **strv;
3120     gint i;
3121
3122     g_variant_builder_init (&builder, G_VARIANT_TYPE ("aas"));
3123     g_variant_builder_open (&builder, G_VARIANT_TYPE ("as"));
3124     for (i = 0; i < 6; i++)
3125       if (i & 1)
3126         g_variant_builder_add (&builder, "s", strvector[i]);
3127       else
3128         g_variant_builder_add (&builder, "&s", strvector[i]);
3129     g_variant_builder_close (&builder);
3130     g_variant_builder_add (&builder, "^as", strvector);
3131     g_variant_builder_add (&builder, "^as", strvector);
3132     value = g_variant_new ("aas", &builder);
3133
3134     g_variant_iter_init (&iter, value);
3135     while (g_variant_iter_loop (&iter, "^as", &strv))
3136       for (i = 0; i < 6; i++)
3137         g_assert_cmpstr (strv[i], ==, strvector[i]);
3138
3139     g_variant_iter_init (&iter, value);
3140     while (g_variant_iter_loop (&iter, "^a&s", &strv))
3141       for (i = 0; i < 6; i++)
3142         g_assert_cmpstr (strv[i], ==, strvector[i]);
3143
3144     g_variant_iter_init (&iter, value);
3145     while (g_variant_iter_loop (&iter, "as", &i2))
3146       {
3147         gchar *str;
3148
3149         i = 0;
3150         while (g_variant_iter_loop (i2, "s", &str))
3151           g_assert_cmpstr (str, ==, strvector[i++]);
3152         g_assert (i == 6);
3153       }
3154
3155     g_variant_iter_init (&iter, value);
3156     i3 = g_variant_iter_copy (&iter);
3157     while (g_variant_iter_loop (&iter, "@as", &sub))
3158       {
3159         gchar *str = g_variant_print (sub, TRUE);
3160         g_assert_cmpstr (str, ==,
3161                          "['i', 'ii', 'iii', 'iv', 'v', 'vi']");
3162         g_free (str);
3163       }
3164
3165     g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
3166                            "*NULL has already been returned*");
3167     g_variant_iter_next_value (&iter);
3168     g_test_assert_expected_messages ();
3169
3170     while (g_variant_iter_loop (i3, "*", &sub))
3171       {
3172         gchar *str = g_variant_print (sub, TRUE);
3173         g_assert_cmpstr (str, ==,
3174                          "['i', 'ii', 'iii', 'iv', 'v', 'vi']");
3175         g_free (str);
3176       }
3177
3178     g_variant_iter_free (i3);
3179
3180     for (i = 0; i < g_variant_n_children (value); i++)
3181       {
3182         gint j;
3183
3184         g_variant_get_child (value, i, "*", &sub);
3185
3186         for (j = 0; j < g_variant_n_children (sub); j++)
3187           {
3188             const gchar *str = NULL;
3189             GVariant *cval;
3190
3191             g_variant_get_child (sub, j, "&s", &str);
3192             g_assert_cmpstr (str, ==, strvector[j]);
3193
3194             cval = g_variant_get_child_value (sub, j);
3195             g_variant_get (cval, "&s", &str);
3196             g_assert_cmpstr (str, ==, strvector[j]);
3197             g_variant_unref (cval);
3198           }
3199
3200         g_variant_unref (sub);
3201       }
3202
3203     g_variant_unref (value);
3204   }
3205
3206   {
3207     gboolean justs[10];
3208     GVariant *value;
3209
3210     GVariant *vval;
3211     guchar byteval;
3212     gboolean bval;
3213     gint16 i16val;
3214     guint16 u16val;
3215     gint32 i32val;
3216     guint32 u32val;
3217     gint64 i64val;
3218     guint64 u64val;
3219     gdouble dval;
3220     gint32 hval;
3221
3222     /* test all 'nothing' */
3223     value = g_variant_new ("(mymbmnmqmimumxmtmhmdmv)",
3224                            FALSE, 'a',
3225                            FALSE, TRUE,
3226                            FALSE, (gint16) 123,
3227                            FALSE, (guint16) 123,
3228                            FALSE, (gint32) 123,
3229                            FALSE, (guint32) 123,
3230                            FALSE, (gint64) 123,
3231                            FALSE, (guint64) 123,
3232                            FALSE, (gint32) -1,
3233                            FALSE, (gdouble) 37.5,
3234                            NULL);
3235
3236     /* both NULL */
3237     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3238                    NULL, NULL,
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);
3249
3250     /* NULL values */
3251     memset (justs, 1, sizeof justs);
3252     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3253                    &justs[0], NULL,
3254                    &justs[1], NULL,
3255                    &justs[2], NULL,
3256                    &justs[3], NULL,
3257                    &justs[4], NULL,
3258                    &justs[5], NULL,
3259                    &justs[6], NULL,
3260                    &justs[7], NULL,
3261                    &justs[8], NULL,
3262                    &justs[9], NULL,
3263                    NULL);
3264     g_assert (!(justs[0] || justs[1] || justs[2] || justs[3] || justs[4] ||
3265                 justs[5] || justs[6] || justs[7] || justs[8] || justs[9]));
3266
3267     /* both non-NULL */
3268     memset (justs, 1, sizeof justs);
3269     byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3270     vval = (void *) 1;
3271     bval = TRUE;
3272     dval = 88.88;
3273     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3274                    &justs[0], &byteval,
3275                    &justs[1], &bval,
3276                    &justs[2], &i16val,
3277                    &justs[3], &u16val,
3278                    &justs[4], &i32val,
3279                    &justs[5], &u32val,
3280                    &justs[6], &i64val,
3281                    &justs[7], &u64val,
3282                    &justs[8], &hval,
3283                    &justs[9], &dval,
3284                    &vval);
3285     g_assert (!(justs[0] || justs[1] || justs[2] || justs[3] || justs[4] ||
3286                 justs[5] || justs[6] || justs[7] || justs[8] || justs[9]));
3287     g_assert (byteval == '\0' && bval == FALSE);
3288     g_assert (i16val == 0 && u16val == 0 && i32val == 0 &&
3289               u32val == 0 && i64val == 0 && u64val == 0 &&
3290               hval == 0 && dval == 0.0);
3291     g_assert (vval == NULL);
3292
3293     /* NULL justs */
3294     byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3295     vval = (void *) 1;
3296     bval = TRUE;
3297     dval = 88.88;
3298     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3299                    NULL, &byteval,
3300                    NULL, &bval,
3301                    NULL, &i16val,
3302                    NULL, &u16val,
3303                    NULL, &i32val,
3304                    NULL, &u32val,
3305                    NULL, &i64val,
3306                    NULL, &u64val,
3307                    NULL, &hval,
3308                    NULL, &dval,
3309                    &vval);
3310     g_assert (byteval == '\0' && bval == FALSE);
3311     g_assert (i16val == 0 && u16val == 0 && i32val == 0 &&
3312               u32val == 0 && i64val == 0 && u64val == 0 &&
3313               hval == 0 && dval == 0.0);
3314     g_assert (vval == NULL);
3315
3316     g_variant_unref (value);
3317
3318
3319     /* test all 'just' */
3320     value = g_variant_new ("(mymbmnmqmimumxmtmhmdmv)",
3321                            TRUE, 'a',
3322                            TRUE, TRUE,
3323                            TRUE, (gint16) 123,
3324                            TRUE, (guint16) 123,
3325                            TRUE, (gint32) 123,
3326                            TRUE, (guint32) 123,
3327                            TRUE, (gint64) 123,
3328                            TRUE, (guint64) 123,
3329                            TRUE, (gint32) -1,
3330                            TRUE, (gdouble) 37.5,
3331                            g_variant_new ("()"));
3332
3333     /* both NULL */
3334     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3335                    NULL, NULL,
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);
3346
3347     /* NULL values */
3348     memset (justs, 0, sizeof justs);
3349     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3350                    &justs[0], NULL,
3351                    &justs[1], NULL,
3352                    &justs[2], NULL,
3353                    &justs[3], NULL,
3354                    &justs[4], NULL,
3355                    &justs[5], NULL,
3356                    &justs[6], NULL,
3357                    &justs[7], NULL,
3358                    &justs[8], NULL,
3359                    &justs[9], NULL,
3360                    NULL);
3361     g_assert (justs[0] && justs[1] && justs[2] && justs[3] && justs[4] &&
3362               justs[5] && justs[6] && justs[7] && justs[8] && justs[9]);
3363
3364     /* both non-NULL */
3365     memset (justs, 0, sizeof justs);
3366     byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3367     vval = (void *) 1;
3368     bval = FALSE;
3369     dval = 88.88;
3370     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3371                    &justs[0], &byteval,
3372                    &justs[1], &bval,
3373                    &justs[2], &i16val,
3374                    &justs[3], &u16val,
3375                    &justs[4], &i32val,
3376                    &justs[5], &u32val,
3377                    &justs[6], &i64val,
3378                    &justs[7], &u64val,
3379                    &justs[8], &hval,
3380                    &justs[9], &dval,
3381                    &vval);
3382     g_assert (justs[0] && justs[1] && justs[2] && justs[3] && justs[4] &&
3383               justs[5] && justs[6] && justs[7] && justs[8] && justs[9]);
3384     g_assert (byteval == 'a' && bval == TRUE);
3385     g_assert (i16val == 123 && u16val == 123 && i32val == 123 &&
3386               u32val == 123 && i64val == 123 && u64val == 123 &&
3387               hval == -1 && dval == 37.5);
3388     g_assert (g_variant_is_of_type (vval, G_VARIANT_TYPE_UNIT));
3389     g_variant_unref (vval);
3390
3391     /* NULL justs */
3392     byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3393     vval = (void *) 1;
3394     bval = TRUE;
3395     dval = 88.88;
3396     g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3397                    NULL, &byteval,
3398                    NULL, &bval,
3399                    NULL, &i16val,
3400                    NULL, &u16val,
3401                    NULL, &i32val,
3402                    NULL, &u32val,
3403                    NULL, &i64val,
3404                    NULL, &u64val,
3405                    NULL, &hval,
3406                    NULL, &dval,
3407                    &vval);
3408     g_assert (byteval == 'a' && bval == TRUE);
3409     g_assert (i16val == 123 && u16val == 123 && i32val == 123 &&
3410               u32val == 123 && i64val == 123 && u64val == 123 &&
3411               hval == -1 && dval == 37.5);
3412     g_assert (g_variant_is_of_type (vval, G_VARIANT_TYPE_UNIT));
3413     g_variant_unref (vval);
3414
3415     g_variant_unref (value);
3416   }
3417
3418   {
3419     GVariant *value;
3420     gchar *str;
3421
3422     value = g_variant_new ("(masas)", NULL, NULL);
3423     g_variant_ref_sink (value);
3424
3425     str = g_variant_print (value, TRUE);
3426     g_assert_cmpstr (str, ==, "(@mas nothing, @as [])");
3427     g_variant_unref (value);
3428     g_free (str);
3429
3430     do_failed_test ("/gvariant/varargs/subprocess/empty-array",
3431                     "*which type of empty array*");
3432   }
3433
3434   g_variant_type_info_assert_no_infos ();
3435 }
3436
3437 static void
3438 hash_get (GVariant    *value,
3439           const gchar *format,
3440           ...)
3441 {
3442   const gchar *endptr = NULL;
3443   gboolean hash;
3444   va_list ap;
3445
3446   hash = g_str_has_suffix (format, "#");
3447
3448   va_start (ap, format);
3449   g_variant_get_va (value, format, hash ? &endptr : NULL, &ap);
3450   va_end (ap);
3451
3452   if (hash)
3453     g_assert (*endptr == '#');
3454 }
3455
3456 static GVariant *
3457 hash_new (const gchar *format,
3458           ...)
3459 {
3460   const gchar *endptr = NULL;
3461   GVariant *value;
3462   gboolean hash;
3463   va_list ap;
3464
3465   hash = g_str_has_suffix (format, "#");
3466
3467   va_start (ap, format);
3468   value = g_variant_new_va (format, hash ? &endptr : NULL, &ap);
3469   va_end (ap);
3470
3471   if (hash)
3472     g_assert (*endptr == '#');
3473
3474   return value;
3475 }
3476
3477 static void
3478 test_valist (void)
3479 {
3480   GVariant *value;
3481   gint32 x;
3482
3483   x = 0;
3484   value = hash_new ("i", 234);
3485   hash_get (value, "i", &x);
3486   g_assert (x == 234);
3487   g_variant_unref (value);
3488
3489   x = 0;
3490   value = hash_new ("i#", 234);
3491   hash_get (value, "i#", &x);
3492   g_assert (x == 234);
3493   g_variant_unref (value);
3494
3495   g_variant_type_info_assert_no_infos ();
3496 }
3497
3498 static void
3499 test_builder_memory (void)
3500 {
3501   GVariantBuilder *hb;
3502   GVariantBuilder sb;
3503
3504   hb = g_variant_builder_new  (G_VARIANT_TYPE_ARRAY);
3505   g_variant_builder_open (hb, 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_add (hb, "s", "some value");
3509   g_variant_builder_ref (hb);
3510   g_variant_builder_unref (hb);
3511   g_variant_builder_unref (hb);
3512
3513   hb = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
3514   g_variant_builder_unref (hb);
3515
3516   hb = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
3517   g_variant_builder_clear (hb);
3518   g_variant_builder_unref (hb);
3519
3520   g_variant_builder_init (&sb, G_VARIANT_TYPE_ARRAY);
3521   g_variant_builder_open (&sb, G_VARIANT_TYPE_ARRAY);
3522   g_variant_builder_open (&sb, G_VARIANT_TYPE_ARRAY);
3523   g_variant_builder_add (&sb, "s", "some value");
3524   g_variant_builder_clear (&sb);
3525
3526   g_variant_type_info_assert_no_infos ();
3527 }
3528
3529 static void
3530 test_hashing (void)
3531 {
3532   GVariant *items[4096];
3533   GHashTable *table;
3534   gint i;
3535
3536   table = g_hash_table_new_full (g_variant_hash, g_variant_equal,
3537                                  (GDestroyNotify ) g_variant_unref,
3538                                  NULL);
3539
3540   for (i = 0; i < G_N_ELEMENTS (items); i++)
3541     {
3542       TreeInstance *tree;
3543       gint j;
3544
3545  again:
3546       tree = tree_instance_new (NULL, 0);
3547       items[i] = tree_instance_get_gvariant (tree);
3548       tree_instance_free (tree);
3549
3550       for (j = 0; j < i; j++)
3551         if (g_variant_equal (items[i], items[j]))
3552           {
3553             g_variant_unref (items[i]);
3554             goto again;
3555           }
3556
3557       g_hash_table_insert (table,
3558                            g_variant_ref_sink (items[i]),
3559                            GINT_TO_POINTER (i));
3560     }
3561
3562   for (i = 0; i < G_N_ELEMENTS (items); i++)
3563     {
3564       gpointer result;
3565
3566       result = g_hash_table_lookup (table, items[i]);
3567       g_assert_cmpint (GPOINTER_TO_INT (result), ==, i);
3568     }
3569
3570   g_hash_table_unref (table);
3571
3572   g_variant_type_info_assert_no_infos ();
3573 }
3574
3575 static void
3576 test_gv_byteswap (void)
3577 {
3578 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
3579 # define native16(x)  x, 0
3580 # define swapped16(x) 0, x
3581 #else
3582 # define native16(x)  0, x
3583 # define swapped16(x) x, 0
3584 #endif
3585   /* all kinds of of crazy randomised testing already performed on the
3586    * byteswapper in the /gvariant/serialiser/byteswap test and all kinds
3587    * of crazy randomised testing performed against the serialiser
3588    * normalisation functions in the /gvariant/serialiser/fuzz/ tests.
3589    *
3590    * just test a few simple cases here to make sure they each work
3591    */
3592   guchar validbytes[] = { 'a', '\0', swapped16(66), 2,
3593                           0,
3594                           'b', '\0', swapped16(77), 2,
3595                           5, 11 };
3596   guchar corruptbytes[] = { 'a', '\0', swapped16(66), 2,
3597                             0,
3598                             'b', '\0', swapped16(77), 2,
3599                             6, 11 };
3600   guint valid_data[4], corrupt_data[4];
3601   GVariant *value, *swapped;
3602   gchar *string, *string2;
3603
3604   memcpy (valid_data, validbytes, sizeof validbytes);
3605   memcpy (corrupt_data, corruptbytes, sizeof corruptbytes);
3606
3607   /* trusted */
3608   value = g_variant_new_from_data (G_VARIANT_TYPE ("a(sn)"),
3609                                    valid_data, sizeof validbytes, TRUE,
3610                                    NULL, NULL);
3611   swapped = g_variant_byteswap (value);
3612   g_variant_unref (value);
3613   g_assert (g_variant_get_size (swapped) == 13);
3614   string = g_variant_print (swapped, FALSE);
3615   g_variant_unref (swapped);
3616   g_assert_cmpstr (string, ==, "[('a', 66), ('b', 77)]");
3617   g_free (string);
3618
3619   /* untrusted but valid */
3620   value = g_variant_new_from_data (G_VARIANT_TYPE ("a(sn)"),
3621                                    valid_data, sizeof validbytes, FALSE,
3622                                    NULL, NULL);
3623   swapped = g_variant_byteswap (value);
3624   g_variant_unref (value);
3625   g_assert (g_variant_get_size (swapped) == 13);
3626   string = g_variant_print (swapped, FALSE);
3627   g_variant_unref (swapped);
3628   g_assert_cmpstr (string, ==, "[('a', 66), ('b', 77)]");
3629   g_free (string);
3630
3631   /* untrusted, invalid */
3632   value = g_variant_new_from_data (G_VARIANT_TYPE ("a(sn)"),
3633                                    corrupt_data, sizeof corruptbytes, FALSE,
3634                                    NULL, NULL);
3635   string = g_variant_print (value, FALSE);
3636   swapped = g_variant_byteswap (value);
3637   g_variant_unref (value);
3638   g_assert (g_variant_get_size (swapped) == 13);
3639   value = g_variant_byteswap (swapped);
3640   g_variant_unref (swapped);
3641   string2 = g_variant_print (value, FALSE);
3642   g_assert (g_variant_get_size (value) == 13);
3643   g_variant_unref (value);
3644   g_assert_cmpstr (string, ==, string2);
3645   g_free (string2);
3646   g_free (string);
3647 }
3648
3649 static void
3650 test_parser (void)
3651 {
3652   TreeInstance *tree;
3653   GVariant *parsed;
3654   GVariant *value;
3655   gchar *pt, *p;
3656   gchar *res;
3657
3658   tree = tree_instance_new (NULL, 3);
3659   value = tree_instance_get_gvariant (tree);
3660   tree_instance_free (tree);
3661
3662   pt = g_variant_print (value, TRUE);
3663   p = g_variant_print (value, FALSE);
3664
3665   parsed = g_variant_parse (NULL, pt, NULL, NULL, NULL);
3666   res = g_variant_print (parsed, FALSE);
3667   g_assert_cmpstr (p, ==, res);
3668   g_variant_unref (parsed);
3669   g_free (res);
3670
3671   parsed = g_variant_parse (g_variant_get_type (value), p,
3672                             NULL, NULL, NULL);
3673   res = g_variant_print (parsed, TRUE);
3674   g_assert_cmpstr (pt, ==, res);
3675   g_variant_unref (parsed);
3676   g_free (res);
3677
3678   g_variant_unref (value);
3679   g_free (pt);
3680   g_free (p);
3681 }
3682
3683 static void
3684 test_parses (void)
3685 {
3686   gint i;
3687
3688   for (i = 0; i < 100; i++)
3689     {
3690       test_parser ();
3691     }
3692
3693   /* mini test */
3694   {
3695     GError *error = NULL;
3696     gchar str[128];
3697     GVariant *val;
3698     gchar *p, *p2;
3699
3700     for (i = 0; i < 127; i++)
3701       str[i] = i + 1;
3702     str[i] = 0;
3703
3704     val = g_variant_new_string (str);
3705     p = g_variant_print (val, FALSE);
3706     g_variant_unref (val);
3707
3708     val = g_variant_parse (NULL, p, NULL, NULL, &error);
3709     p2 = g_variant_print (val, FALSE);
3710
3711     g_assert_cmpstr (str, ==, g_variant_get_string (val, NULL));
3712     g_assert_cmpstr (p, ==, p2);
3713
3714     g_variant_unref (val);
3715     g_free (p2);
3716     g_free (p);
3717   }
3718
3719   /* another mini test */
3720   {
3721     const gchar *end;
3722     GVariant *value;
3723
3724     value = g_variant_parse (G_VARIANT_TYPE_INT32, "1 2 3", NULL, &end, NULL);
3725     g_assert_cmpint (g_variant_get_int32 (value), ==, 1);
3726     /* make sure endptr returning works */
3727     g_assert_cmpstr (end, ==, " 2 3");
3728     g_variant_unref (value);
3729   }
3730
3731   /* unicode mini test */
3732   {
3733     /* ał𝄞 */
3734     const gchar orig[] = "a\xc5\x82\xf0\x9d\x84\x9e \t\n";
3735     GVariant *value;
3736     gchar *printed;
3737
3738     value = g_variant_new_string (orig);
3739     printed = g_variant_print (value, FALSE);
3740     g_variant_unref (value);
3741
3742     g_assert_cmpstr (printed, ==, "'a\xc5\x82\xf0\x9d\x84\x9e \\t\\n'");
3743     value = g_variant_parse (NULL, printed, NULL, NULL, NULL);
3744     g_assert_cmpstr (g_variant_get_string (value, NULL), ==, orig);
3745     g_variant_unref (value);
3746     g_free (printed);
3747   }
3748
3749   /* escapes */
3750   {
3751     const gchar orig[] = " \342\200\254 \360\220\210\240 \a \b \f \n \r \t \v ";
3752     GVariant *value;
3753     gchar *printed;
3754
3755     value = g_variant_new_string (orig);
3756     printed = g_variant_print (value, FALSE);
3757     g_variant_unref (value);
3758
3759     g_assert_cmpstr (printed, ==, "' \\u202c \\U00010220 \\a \\b \\f \\n \\r \\t \\v '");
3760     value = g_variant_parse (NULL, printed, NULL, NULL, NULL);
3761     g_assert_cmpstr (g_variant_get_string (value, NULL), ==, orig);
3762     g_variant_unref (value);
3763     g_free (printed);
3764   }
3765
3766 #ifndef _MSC_VER
3767   /* inf/nan strings are C99 features which Visual C++ does not support */
3768   /* inf/nan mini test */
3769   {
3770     const gchar *tests[] = { "inf", "-inf", "nan" };
3771     GVariant *value;
3772     gchar *printed;
3773     gchar *printed_down;
3774     gint i;
3775
3776     for (i = 0; i < G_N_ELEMENTS (tests); i++)
3777       {
3778         GError *error = NULL;
3779         value = g_variant_parse (NULL, tests[i], NULL, NULL, &error);
3780         printed = g_variant_print (value, FALSE);
3781         /* Canonicalize to lowercase; https://bugzilla.gnome.org/show_bug.cgi?id=704585 */
3782         printed_down = g_ascii_strdown (printed, -1);
3783         g_assert (g_str_has_prefix (printed_down, tests[i]));
3784         g_free (printed);
3785         g_free (printed_down);
3786         g_variant_unref (value);
3787       }
3788   }
3789 #endif
3790
3791   g_variant_type_info_assert_no_infos ();
3792 }
3793
3794 static void
3795 test_parse_failures (void)
3796 {
3797   const gchar *test[] = {
3798     "[1, 2,",                   "6:",              "expected value",
3799     "",                         "0:",              "expected value",
3800     "(1, 2,",                   "6:",              "expected value",
3801     "<1",                       "2:",              "expected '>'",
3802     "[]",                       "0-2:",            "unable to infer",
3803     "(,",                       "1:",              "expected value",
3804     "[4,'']",                   "1-2,3-5:",        "common type",
3805     "[4, '', 5]",               "1-2,4-6:",        "common type",
3806     "['', 4, 5]",               "1-3,5-6:",        "common type",
3807     "[4, 5, '']",               "1-2,7-9:",        "common type",
3808     "[[4], [], ['']]",          "1-4,10-14:",      "common type",
3809     "[[], [4], ['']]",          "5-8,10-14:",      "common type",
3810     "just",                     "4:",              "expected value",
3811     "nothing",                  "0-7:",            "unable to infer",
3812     "just [4, '']",             "6-7,9-11:",       "common type",
3813     "[[4,'']]",                 "2-3,4-6:",        "common type",
3814     "([4,''],)",                "2-3,4-6:",        "common type",
3815     "(4)",                      "2:",              "','",
3816     "{}",                       "0-2:",            "unable to infer",
3817     "{[1,2],[3,4]}",            "0-13:",           "basic types",
3818     "{[1,2]:[3,4]}",            "0-13:",           "basic types",
3819     "justt",                    "0-5:",            "unknown keyword",
3820     "nothng",                   "0-6:",            "unknown keyword",
3821     "uint33",                   "0-6:",            "unknown keyword",
3822     "@mi just ''",              "9-11:",           "can not parse as",
3823     "@ai ['']",                 "5-7:",            "can not parse as",
3824     "@(i) ('',)",               "6-8:",            "can not parse as",
3825     "[[], 5]",                  "1-3,5-6:",        "common type",
3826     "[[5], 5]",                 "1-4,6-7:",        "common type",
3827     "5 5",                      "2:",              "expected end of input",
3828     "[5, [5, '']]",             "5-6,8-10:",       "common type",
3829     "@i just 5",                "3-9:",            "can not parse as",
3830     "@i nothing",               "3-10:",           "can not parse as",
3831     "@i []",                    "3-5:",            "can not parse as",
3832     "@i ()",                    "3-5:",            "can not parse as",
3833     "@ai (4,)",                 "4-8:",            "can not parse as",
3834     "@(i) []",                  "5-7:",            "can not parse as",
3835     "(5 5)",                    "3:",              "expected ','",
3836     "[5 5]",                    "3:",              "expected ',' or ']'",
3837     "(5, 5 5)",                 "6:",              "expected ',' or ')'",
3838     "[5, 5 5]",                 "6:",              "expected ',' or ']'",
3839     "<@i []>",                  "4-6:",            "can not parse as",
3840     "<[5 5]>",                  "4:",              "expected ',' or ']'",
3841     "{[4,''],5}",               "2-3,4-6:",        "common type",
3842     "{5,[4,'']}",               "4-5,6-8:",        "common type",
3843     "@i {1,2}",                 "3-8:",            "can not parse as",
3844     "{@i '', 5}",               "4-6:",            "can not parse as",
3845     "{5, @i ''}",               "7-9:",            "can not parse as",
3846     "@ai {}",                   "4-6:",            "can not parse as",
3847     "{@i '': 5}",               "4-6:",            "can not parse as",
3848     "{5: @i ''}",               "7-9:",            "can not parse as",
3849     "{<4,5}",                   "3:",              "expected '>'",
3850     "{4,<5}",                   "5:",              "expected '>'",
3851     "{4,5,6}",                  "4:",              "expected '}'",
3852     "{5 5}",                    "3:",              "expected ':' or ','",
3853     "{4: 5: 6}",                "5:",              "expected ',' or '}'",
3854     "{4:5,<6:7}",               "7:",              "expected '>'",
3855     "{4:5,6:<7}",               "9:",              "expected '>'",
3856     "{4:5,6 7}",                "7:",              "expected ':'",
3857     "@o 'foo'",                 "3-8:",            "object path",
3858     "@g 'zzz'",                 "3-8:",            "signature",
3859     "@i true",                  "3-7:",            "can not parse as",
3860     "@z 4",                     "0-2:",            "invalid type",
3861     "@a* []",                   "0-3:",            "definite",
3862     "@ai [3 3]",                "7:",              "expected ',' or ']'",
3863     "18446744073709551616",     "0-20:",           "too big for any type",
3864     "-18446744073709551616",    "0-21:",           "too big for any type",
3865     "byte 256",                 "5-8:",            "out of range for type",
3866     "byte -1",                  "5-7:",            "out of range for type",
3867     "int16 32768",              "6-11:",           "out of range for type",
3868     "int16 -32769",             "6-12:",           "out of range for type",
3869     "uint16 -1",                "7-9:",            "out of range for type",
3870     "uint16 65536",             "7-12:",           "out of range for type",
3871     "2147483648",               "0-10:",           "out of range for type",
3872     "-2147483649",              "0-11:",           "out of range for type",
3873     "uint32 -1",                "7-9:",            "out of range for type",
3874     "uint32 4294967296",        "7-17:",           "out of range for type",
3875     "@x 9223372036854775808",   "3-22:",           "out of range for type",
3876     "@x -9223372036854775809",  "3-23:",           "out of range for type",
3877     "@t -1",                    "3-5:",            "out of range for type",
3878     "@t 18446744073709551616",  "3-23:",           "too big for any type",
3879     "handle 2147483648",        "7-17:",           "out of range for type",
3880     "handle -2147483649",       "7-18:",           "out of range for type",
3881     "1.798e308",                "0-9:",            "too big for any type",
3882     "37.5a488",                 "4-5:",            "invalid character",
3883     "0x7ffgf",                  "5-6:",            "invalid character",
3884     "07758",                    "4-5:",            "invalid character",
3885     "123a5",                    "3-4:",            "invalid character",
3886     "@ai 123",                  "4-7:",            "can not parse as",
3887     "'\"\\'",                   "0-4:",            "unterminated string",
3888     "'\"\\'\\",                 "0-5:",            "unterminated string",
3889     "boolean 4",                "8-9:",            "can not parse as",
3890     "int32 true",               "6-10:",           "can not parse as",
3891     "[double 5, int32 5]",      "1-9,11-18:",      "common type",
3892     "string 4",                 "7-8:",            "can not parse as",
3893     "\x0a",                     "1:",              "expected value",
3894     "((",                       "2:",              "expected value",
3895     "(b",                       "1:",              "expected value",
3896     "b'",                       "0-2:",            "unterminated string constant",
3897     "b\"",                      "0-2:",            "unterminated string constant",
3898     "b'a",                      "0-3:",            "unterminated string constant",
3899     "b\"a",                     "0-3:",            "unterminated string constant",
3900     "b'\\",                     "0-3:",            "unterminated string constant",
3901     "b\"\\",                    "0-3:",            "unterminated string constant",
3902     "b'\\'",                    "0-4:",            "unterminated string constant",
3903     "b\"\\\"",                  "0-4:",            "unterminated string constant",
3904     "b'\\'a",                   "0-5:",            "unterminated string constant",
3905     "b\"\\\"a",                 "0-5:",            "unterminated string constant",
3906   };
3907   gint i;
3908
3909   for (i = 0; i < G_N_ELEMENTS (test); i += 3)
3910     {
3911       GError *error1 = NULL, *error2 = NULL;
3912       GVariant *value;
3913
3914       /* Copy the test string and drop its nul terminator, then use the @limit
3915        * parameter of g_variant_parse() to set the length. This allows valgrind
3916        * to catch 1-byte heap buffer overflows. */
3917       gsize test_len = MAX (strlen (test[i]), 1);
3918       gchar *test_blob = g_malloc0 (test_len);  /* no nul terminator */
3919
3920       memcpy (test_blob, test[i], test_len);
3921       value = g_variant_parse (NULL, test_blob, test_blob + test_len, NULL, &error1);
3922       g_assert_null (value);
3923
3924       g_free (test_blob);
3925
3926       if (!strstr (error1->message, test[i+2]))
3927         g_error ("test %d: Can't find '%s' in '%s'", i / 3,
3928                  test[i+2], error1->message);
3929
3930       if (!g_str_has_prefix (error1->message, test[i+1]))
3931         g_error ("test %d: Expected location '%s' in '%s'", i / 3,
3932                  test[i+1], error1->message);
3933
3934       /* Test again with the nul terminator this time. The behaviour should be
3935        * the same. */
3936       value = g_variant_parse (NULL, test[i], NULL, NULL, &error2);
3937       g_assert_null (value);
3938
3939       g_assert_cmpint (error1->domain, ==, error2->domain);
3940       g_assert_cmpint (error1->code, ==, error2->code);
3941       g_assert_cmpstr (error1->message, ==, error2->message);
3942
3943       g_clear_error (&error1);
3944       g_clear_error (&error2);
3945     }
3946 }
3947
3948 static void
3949 test_parse_bad_format_char (void)
3950 {
3951   g_variant_new_parsed ("%z");
3952
3953   g_assert_not_reached ();
3954 }
3955
3956 static void
3957 test_parse_bad_format_string (void)
3958 {
3959   g_variant_new_parsed ("uint32 %i", 2);
3960
3961   g_assert_not_reached ();
3962 }
3963
3964 static void
3965 test_parse_bad_args (void)
3966 {
3967   g_variant_new_parsed ("%@i", g_variant_new_uint32 (2));
3968
3969   g_assert_not_reached ();
3970 }
3971
3972 static void
3973 test_parse_positional (void)
3974 {
3975   GVariant *value;
3976   check_and_free (g_variant_new_parsed ("[('one', 1), (%s, 2),"
3977                                         " ('three', %i)]", "two", 3),
3978                   "[('one', 1), ('two', 2), ('three', 3)]");
3979   value = g_variant_new_parsed ("[('one', 1), (%s, 2),"
3980                                 " ('three', %u)]", "two", 3);
3981   g_assert (g_variant_is_of_type (value, G_VARIANT_TYPE ("a(su)")));
3982   check_and_free (value, "[('one', 1), ('two', 2), ('three', 3)]");
3983   check_and_free (g_variant_new_parsed ("{%s:%i}", "one", 1), "{'one': 1}");
3984
3985   if (g_test_undefined ())
3986     {
3987       do_failed_test ("/gvariant/parse/subprocess/bad-format-char",
3988                       "*GVariant format string*");
3989
3990       do_failed_test ("/gvariant/parse/subprocess/bad-format-string",
3991                       "*can not parse as*");
3992
3993       do_failed_test ("/gvariant/parse/subprocess/bad-args",
3994                       "*expected GVariant of type 'i'*");
3995     }
3996 }
3997
3998 static void
3999 test_floating (void)
4000 {
4001   GVariant *value;
4002
4003   value = g_variant_new_int32 (42);
4004   g_assert (g_variant_is_floating (value));
4005   g_variant_ref_sink (value);
4006   g_assert (!g_variant_is_floating (value));
4007   g_variant_unref (value);
4008 }
4009
4010 static void
4011 test_bytestring (void)
4012 {
4013   const gchar *test_string = "foo,bar,baz,quux,\xffoooo";
4014   GVariant *value;
4015   gchar **strv;
4016   gchar *str;
4017   const gchar *const_str;
4018   GVariant *untrusted_empty;
4019
4020   strv = g_strsplit (test_string, ",", 0);
4021
4022   value = g_variant_new_bytestring_array ((const gchar **) strv, -1);
4023   g_assert (g_variant_is_floating (value));
4024   g_strfreev (strv);
4025
4026   str = g_variant_print (value, FALSE);
4027   g_variant_unref (value);
4028
4029   value = g_variant_parse (NULL, str, NULL, NULL, NULL);
4030   g_free (str);
4031
4032   strv = g_variant_dup_bytestring_array (value, NULL);
4033   g_variant_unref (value);
4034
4035   str = g_strjoinv (",", strv);
4036   g_strfreev (strv);
4037
4038   g_assert_cmpstr (str, ==, test_string);
4039   g_free (str);
4040
4041   strv = g_strsplit (test_string, ",", 0);
4042   value = g_variant_new ("(^aay^a&ay^ay^&ay)",
4043                          strv, strv, strv[0], strv[0]);
4044   g_strfreev (strv);
4045
4046   g_variant_get_child (value, 0, "^a&ay", &strv);
4047   str = g_strjoinv (",", strv);
4048   g_free (strv);
4049   g_assert_cmpstr (str, ==, test_string);
4050   g_free (str);
4051
4052   g_variant_get_child (value, 0, "^aay", &strv);
4053   str = g_strjoinv (",", strv);
4054   g_strfreev (strv);
4055   g_assert_cmpstr (str, ==, test_string);
4056   g_free (str);
4057
4058   g_variant_get_child (value, 1, "^a&ay", &strv);
4059   str = g_strjoinv (",", strv);
4060   g_free (strv);
4061   g_assert_cmpstr (str, ==, test_string);
4062   g_free (str);
4063
4064   g_variant_get_child (value, 1, "^aay", &strv);
4065   str = g_strjoinv (",", strv);
4066   g_strfreev (strv);
4067   g_assert_cmpstr (str, ==, test_string);
4068   g_free (str);
4069
4070   g_variant_get_child (value, 2, "^ay", &str);
4071   g_assert_cmpstr (str, ==, "foo");
4072   g_free (str);
4073
4074   g_variant_get_child (value, 2, "^&ay", &str);
4075   g_assert_cmpstr (str, ==, "foo");
4076
4077   g_variant_get_child (value, 3, "^ay", &str);
4078   g_assert_cmpstr (str, ==, "foo");
4079   g_free (str);
4080
4081   g_variant_get_child (value, 3, "^&ay", &str);
4082   g_assert_cmpstr (str, ==, "foo");
4083   g_variant_unref (value);
4084
4085   untrusted_empty = g_variant_new_from_data (G_VARIANT_TYPE ("ay"), NULL, 0, FALSE, NULL, NULL);
4086   value = g_variant_get_normal_form (untrusted_empty);
4087   const_str = g_variant_get_bytestring (value);
4088   (void) const_str;
4089   g_variant_unref (value);
4090   g_variant_unref (untrusted_empty);
4091 }
4092
4093 static void
4094 test_lookup_value (void)
4095 {
4096   struct {
4097     const gchar *dict, *key, *value;
4098   } cases[] = {
4099     { "@a{ss} {'x':  'y'}",   "x",  "'y'" },
4100     { "@a{ss} {'x':  'y'}",   "y"         },
4101     { "@a{os} {'/x': 'y'}",   "/x", "'y'" },
4102     { "@a{os} {'/x': 'y'}",   "/y"        },
4103     { "@a{sv} {'x':  <'y'>}", "x",  "'y'" },
4104     { "@a{sv} {'x':  <5>}",   "x",  "5"   },
4105     { "@a{sv} {'x':  <'y'>}", "y"         }
4106   };
4107   gint i;
4108
4109   for (i = 0; i < G_N_ELEMENTS (cases); i++)
4110     {
4111       GVariant *dictionary;
4112       GVariant *value;
4113       gchar *p;
4114       
4115       dictionary = g_variant_parse (NULL, cases[i].dict, NULL, NULL, NULL);
4116       value = g_variant_lookup_value (dictionary, cases[i].key, NULL);
4117       g_variant_unref (dictionary);
4118
4119       if (value == NULL && cases[i].value == NULL)
4120         continue;
4121
4122       g_assert (value && cases[i].value);
4123       p = g_variant_print (value, FALSE);
4124       g_assert_cmpstr (cases[i].value, ==, p);
4125       g_variant_unref (value);
4126       g_free (p);
4127     }
4128 }
4129
4130 static void
4131 test_lookup (void)
4132 {
4133   const gchar *str;
4134   GVariant *dict;
4135   gboolean ok;
4136   gint num;
4137
4138   dict = g_variant_parse (NULL,
4139                           "{'a': <5>, 'b': <'c'>}",
4140                           NULL, NULL, NULL);
4141
4142   ok = g_variant_lookup (dict, "a", "i", &num);
4143   g_assert (ok);
4144   g_assert_cmpint (num, ==, 5);
4145
4146   ok = g_variant_lookup (dict, "a", "&s", &str);
4147   g_assert (!ok);
4148
4149   ok = g_variant_lookup (dict, "q", "&s", &str);
4150   g_assert (!ok);
4151
4152   ok = g_variant_lookup (dict, "b", "i", &num);
4153   g_assert (!ok);
4154
4155   ok = g_variant_lookup (dict, "b", "&s", &str);
4156   g_assert (ok);
4157   g_assert_cmpstr (str, ==, "c");
4158
4159   ok = g_variant_lookup (dict, "q", "&s", &str);
4160   g_assert (!ok);
4161
4162   g_variant_unref (dict);
4163 }
4164
4165 static GVariant *
4166 untrusted (GVariant *a)
4167 {
4168   GVariant *b;
4169   const GVariantType *type;
4170   GBytes *bytes;
4171
4172   type = g_variant_get_type (a);
4173   bytes = g_variant_get_data_as_bytes (a);
4174   b = g_variant_new_from_bytes (type, bytes, FALSE);
4175   g_bytes_unref (bytes);
4176   g_variant_unref (a);
4177
4178   return b;
4179 }
4180
4181 static void
4182 test_compare (void)
4183 {
4184   GVariant *a;
4185   GVariant *b;
4186
4187   a = untrusted (g_variant_new_byte (5));
4188   b = g_variant_new_byte (6);
4189   g_assert (g_variant_compare (a, b) < 0);
4190   g_variant_unref (a);
4191   g_variant_unref (b);
4192   a = untrusted (g_variant_new_int16 (G_MININT16));
4193   b = g_variant_new_int16 (G_MAXINT16);
4194   g_assert (g_variant_compare (a, b) < 0);
4195   g_variant_unref (a);
4196   g_variant_unref (b);
4197   a = untrusted (g_variant_new_uint16 (0));
4198   b = g_variant_new_uint16 (G_MAXUINT16);
4199   g_assert (g_variant_compare (a, b) < 0);
4200   g_variant_unref (a);
4201   g_variant_unref (b);
4202   a = untrusted (g_variant_new_int32 (G_MININT32));
4203   b = g_variant_new_int32 (G_MAXINT32);
4204   g_assert (g_variant_compare (a, b) < 0);
4205   g_variant_unref (a);
4206   g_variant_unref (b);
4207   a = untrusted (g_variant_new_uint32 (0));
4208   b = g_variant_new_uint32 (G_MAXUINT32);
4209   g_assert (g_variant_compare (a, b) < 0);
4210   g_variant_unref (a);
4211   g_variant_unref (b);
4212   a = untrusted (g_variant_new_int64 (G_MININT64));
4213   b = g_variant_new_int64 (G_MAXINT64);
4214   g_assert (g_variant_compare (a, b) < 0);
4215   g_variant_unref (a);
4216   g_variant_unref (b);
4217   a = untrusted (g_variant_new_uint64 (0));
4218   b = g_variant_new_uint64 (G_MAXUINT64);
4219   g_assert (g_variant_compare (a, b) < 0);
4220   g_variant_unref (a);
4221   g_variant_unref (b);
4222   a = untrusted (g_variant_new_double (G_MINDOUBLE));
4223   b = g_variant_new_double (G_MAXDOUBLE);
4224   g_assert (g_variant_compare (a, b) < 0);
4225   g_variant_unref (a);
4226   g_variant_unref (b);
4227   a = untrusted (g_variant_new_string ("abc"));
4228   b = g_variant_new_string ("abd");
4229   g_assert (g_variant_compare (a, b) < 0);
4230   g_variant_unref (a);
4231   g_variant_unref (b);
4232   a = untrusted (g_variant_new_object_path ("/abc"));
4233   b = g_variant_new_object_path ("/abd");
4234   g_assert (g_variant_compare (a, b) < 0);
4235   g_variant_unref (a);
4236   g_variant_unref (b);
4237   a = untrusted (g_variant_new_signature ("g"));
4238   b = g_variant_new_signature ("o");
4239   g_assert (g_variant_compare (a, b) < 0);
4240   g_variant_unref (a);
4241   g_variant_unref (b);
4242   a = untrusted (g_variant_new_boolean (FALSE));
4243   b = g_variant_new_boolean (TRUE);
4244   g_assert (g_variant_compare (a, b) < 0);
4245   g_variant_unref (a);
4246   g_variant_unref (b);
4247 }
4248
4249 static void
4250 test_equal (void)
4251 {
4252   GVariant *a;
4253   GVariant *b;
4254
4255   a = untrusted (g_variant_new_byte (5));
4256   b = g_variant_get_normal_form (a);
4257   g_assert (g_variant_equal (a, b));
4258   g_variant_unref (a);
4259   g_variant_unref (b);
4260   a = untrusted (g_variant_new_int16 (G_MININT16));
4261   b = g_variant_get_normal_form (a);
4262   g_assert (g_variant_equal (a, b));
4263   g_variant_unref (a);
4264   g_variant_unref (b);
4265   a = untrusted (g_variant_new_uint16 (0));
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_int32 (G_MININT32));
4271   b = g_variant_get_normal_form (a);
4272   g_assert (g_variant_equal (a, b));
4273   g_variant_unref (a);
4274   g_variant_unref (b);
4275   a = untrusted (g_variant_new_uint32 (0));
4276   b = g_variant_get_normal_form (a);
4277   g_assert (g_variant_equal (a, b));
4278   g_variant_unref (a);
4279   g_variant_unref (b);
4280   a = untrusted (g_variant_new_int64 (G_MININT64));
4281   b = g_variant_get_normal_form (a);
4282   g_assert (g_variant_equal (a, b));
4283   g_variant_unref (a);
4284   g_variant_unref (b);
4285   a = untrusted (g_variant_new_uint64 (0));
4286   b = g_variant_get_normal_form (a);
4287   g_assert (g_variant_equal (a, b));
4288   g_variant_unref (a);
4289   g_variant_unref (b);
4290   a = untrusted (g_variant_new_double (G_MINDOUBLE));
4291   b = g_variant_get_normal_form (a);
4292   g_assert (g_variant_equal (a, b));
4293   g_variant_unref (a);
4294   g_variant_unref (b);
4295   a = untrusted (g_variant_new_string ("abc"));
4296   g_assert (g_variant_equal (a, a));
4297   b = g_variant_get_normal_form (a);
4298   g_assert (g_variant_equal (a, b));
4299   g_variant_unref (a);
4300   g_variant_unref (b);
4301   a = untrusted (g_variant_new_object_path ("/abc"));
4302   g_assert (g_variant_equal (a, a));
4303   b = g_variant_get_normal_form (a);
4304   a = untrusted (a);
4305   g_assert (g_variant_equal (a, b));
4306   g_variant_unref (a);
4307   g_variant_unref (b);
4308   a = untrusted (g_variant_new_signature ("g"));
4309   g_assert (g_variant_equal (a, a));
4310   b = g_variant_get_normal_form (a);
4311   a = untrusted (a);
4312   g_assert (g_variant_equal (a, b));
4313   g_variant_unref (a);
4314   g_variant_unref (b);
4315   a = untrusted (g_variant_new_boolean (FALSE));
4316   b = g_variant_get_normal_form (a);
4317   g_assert (g_variant_equal (a, b));
4318   g_variant_unref (a);
4319   g_variant_unref (b);
4320 }
4321
4322 static void
4323 test_fixed_array (void)
4324 {
4325   GVariant *a;
4326   gint32 values[5];
4327   const gint32 *elts;
4328   gsize n_elts;
4329   gint i;
4330
4331   n_elts = 0;
4332   a = g_variant_new_parsed ("[1,2,3,4,5]");
4333   elts = g_variant_get_fixed_array (a, &n_elts, sizeof (gint32));
4334   g_assert (n_elts == 5);
4335   for (i = 0; i < 5; i++)
4336     g_assert_cmpint (elts[i], ==, i + 1);
4337   g_variant_unref (a);
4338
4339   n_elts = 0;
4340   for (i = 0; i < 5; i++)
4341     values[i] = i + 1;
4342   a = g_variant_new_fixed_array (G_VARIANT_TYPE_INT32, values,
4343                                  G_N_ELEMENTS (values), sizeof (values[0]));
4344   g_assert_cmpstr (g_variant_get_type_string (a), ==, "ai");
4345   elts = g_variant_get_fixed_array (a, &n_elts, sizeof (gint32));
4346   g_assert (n_elts == 5);
4347   for (i = 0; i < 5; i++)
4348     g_assert_cmpint (elts[i], ==, i + 1);
4349   g_variant_unref (a);
4350 }
4351
4352 static void
4353 test_check_format_string (void)
4354 {
4355   GVariant *value;
4356
4357   value = g_variant_new ("(sas)", "foo", NULL);
4358   g_variant_ref_sink (value);
4359
4360   g_assert (g_variant_check_format_string (value, "(s*)", TRUE));
4361   g_assert (g_variant_check_format_string (value, "(s*)", FALSE));
4362   g_assert (!g_variant_check_format_string (value, "(u*)", TRUE));
4363   g_assert (!g_variant_check_format_string (value, "(u*)", FALSE));
4364
4365   g_assert (g_variant_check_format_string (value, "(&s*)", FALSE));
4366   g_test_expect_message ("GLib", G_LOG_LEVEL_CRITICAL, "*contains a '&' character*");
4367   g_assert (!g_variant_check_format_string (value, "(&s*)", TRUE));
4368   g_test_assert_expected_messages ();
4369
4370   g_assert (g_variant_check_format_string (value, "(s^as)", TRUE));
4371   g_assert (g_variant_check_format_string (value, "(s^as)", FALSE));
4372
4373   g_test_expect_message ("GLib", G_LOG_LEVEL_CRITICAL, "*contains a '&' character*");
4374   g_assert (!g_variant_check_format_string (value, "(s^a&s)", TRUE));
4375   g_test_assert_expected_messages ();
4376   g_assert (g_variant_check_format_string (value, "(s^a&s)", FALSE));
4377
4378   g_variant_unref (value);
4379
4380   /* Do it again with a type that will let us put a '&' after a '^' */
4381   value = g_variant_new ("(say)", "foo", NULL);
4382   g_variant_ref_sink (value);
4383
4384   g_assert (g_variant_check_format_string (value, "(s*)", TRUE));
4385   g_assert (g_variant_check_format_string (value, "(s*)", FALSE));
4386   g_assert (!g_variant_check_format_string (value, "(u*)", TRUE));
4387   g_assert (!g_variant_check_format_string (value, "(u*)", FALSE));
4388
4389   g_assert (g_variant_check_format_string (value, "(&s*)", FALSE));
4390   g_test_expect_message ("GLib", G_LOG_LEVEL_CRITICAL, "*contains a '&' character*");
4391   g_assert (!g_variant_check_format_string (value, "(&s*)", TRUE));
4392   g_test_assert_expected_messages ();
4393
4394   g_assert (g_variant_check_format_string (value, "(s^ay)", TRUE));
4395   g_assert (g_variant_check_format_string (value, "(s^ay)", FALSE));
4396
4397   g_test_expect_message ("GLib", G_LOG_LEVEL_CRITICAL, "*contains a '&' character*");
4398   g_assert (!g_variant_check_format_string (value, "(s^&ay)", TRUE));
4399   g_test_assert_expected_messages ();
4400   g_assert (g_variant_check_format_string (value, "(s^&ay)", FALSE));
4401
4402   g_assert (g_variant_check_format_string (value, "r", FALSE));
4403   g_assert (g_variant_check_format_string (value, "(?a?)", FALSE));
4404
4405   g_variant_unref (value);
4406 }
4407
4408 static void
4409 verify_gvariant_checksum (const gchar  *sha256,
4410                           GVariant     *v)
4411              
4412 {
4413   gchar *checksum;
4414   checksum = g_compute_checksum_for_data (G_CHECKSUM_SHA256,
4415                                           g_variant_get_data (v),
4416                                           g_variant_get_size (v));
4417   g_assert_cmpstr (sha256, ==, checksum);
4418   g_free (checksum);
4419 }
4420
4421 static void
4422 verify_gvariant_checksum_va (const gchar *sha256,
4423                              const gchar *fmt,
4424                              ...)
4425 {
4426   va_list args;
4427   GVariant *v;
4428
4429   va_start (args, fmt);
4430
4431   v = g_variant_new_va (fmt, NULL, &args);
4432   g_variant_ref_sink (v);
4433 #if G_BYTE_ORDER == G_BIG_ENDIAN
4434   {
4435     GVariant *byteswapped = g_variant_byteswap (v);
4436     g_variant_unref (v);
4437     v = byteswapped;
4438   }
4439 #endif
4440
4441   va_end (args);
4442
4443   verify_gvariant_checksum (sha256, v);
4444
4445   g_variant_unref (v);
4446 }
4447
4448 static void
4449 test_checksum_basic (void)
4450 {
4451   verify_gvariant_checksum_va ("e8a4b2ee7ede79a3afb332b5b6cc3d952a65fd8cffb897f5d18016577c33d7cc",
4452                                "u", 42);
4453   verify_gvariant_checksum_va ("c53e363c33b00cfce298229ee83856b8a98c2e6126cab13f65899f62473b0df5",
4454                                "s", "moocow");
4455   verify_gvariant_checksum_va ("2b4c342f5433ebe591a1da77e013d1b72475562d48578dca8b84bac6651c3cb9",
4456                                "y", 9);
4457   verify_gvariant_checksum_va ("12a3ae445661ce5dee78d0650d33362dec29c4f82af05e7e57fb595bbbacf0ca",
4458                                "t", G_MAXUINT64);
4459   verify_gvariant_checksum_va ("e25a59b24440eb6c833aa79c93b9840e6eab6966add0dacf31df7e9e7000f5b3",
4460                                "d", 3.14159);
4461   verify_gvariant_checksum_va ("4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a",
4462                                "b", TRUE);
4463   verify_gvariant_checksum_va ("ca2fd00fa001190744c15c317643ab092e7048ce086a243e2be9437c898de1bb",
4464                                "q", G_MAXUINT16);
4465 }
4466
4467 static void
4468 test_checksum_nested (void)
4469 {
4470   static const char* const strv[] = {"foo", "bar", "baz", NULL};
4471
4472   verify_gvariant_checksum_va ("31fbc92f08fddaca716188fe4b5d44ae122fc6306fd3c6925af53cfa47ea596d",
4473                                "(uu)", 41, 43);
4474   verify_gvariant_checksum_va ("01759d683cead856d1d386d59af0578841698a424a265345ad5413122f220de8",
4475                                "(su)", "moocow", 79);
4476   verify_gvariant_checksum_va ("52b3ae95f19b3e642ea1d01185aea14a09004c1d1712672644427403a8a0afe6",
4477                                "(qyst)", G_MAXUINT16, 9, "moocow", G_MAXUINT64);
4478   verify_gvariant_checksum_va ("6fc6f4524161c3ae0d316812d7088e3fcd372023edaea2d7821093be40ae1060",
4479                                "(@ay)", g_variant_new_bytestring ("\xFF\xFF\xFF"));
4480   verify_gvariant_checksum_va ("572aca386e1a983dd23bb6eb6e3dfa72eef9ca7c7744581aa800e18d7d9d0b0b",
4481                                "(^as)", strv);
4482   verify_gvariant_checksum_va ("4bddf6174c791bb44fc6a4106573031690064df34b741033a0122ed8dc05bcf3",
4483                                "(yvu)", 254, g_variant_new ("(^as)", strv), 42);
4484 }
4485
4486 static void
4487 test_gbytes (void)
4488 {
4489   GVariant *a;
4490   GVariant *tuple;
4491   GBytes *bytes;
4492   GBytes *bytes2;
4493   const guint8 values[5] = { 1, 2, 3, 4, 5 };
4494   const guint8 *elts;
4495   gsize n_elts;
4496   gint i;
4497
4498   bytes = g_bytes_new (&values, 5);
4499   a = g_variant_new_from_bytes (G_VARIANT_TYPE_BYTESTRING, bytes, TRUE);
4500   g_bytes_unref (bytes);
4501   n_elts = 0;
4502   elts = g_variant_get_fixed_array (a, &n_elts, sizeof (guint8));
4503   g_assert (n_elts == 5);
4504   for (i = 0; i < 5; i++)
4505     g_assert_cmpint (elts[i], ==, i + 1);
4506
4507   bytes2 = g_variant_get_data_as_bytes (a);
4508   g_variant_unref (a);
4509
4510   bytes = g_bytes_new (&values, 5);
4511   g_assert (g_bytes_equal (bytes, bytes2));
4512   g_bytes_unref (bytes);
4513   g_bytes_unref (bytes2);
4514
4515   tuple = g_variant_new_parsed ("['foo', 'bar']");
4516   bytes = g_variant_get_data_as_bytes (tuple); /* force serialisation */
4517   a = g_variant_get_child_value (tuple, 1);
4518   bytes2 = g_variant_get_data_as_bytes (a);
4519   g_assert (!g_bytes_equal (bytes, bytes2));
4520
4521   g_bytes_unref (bytes);
4522   g_bytes_unref (bytes2);
4523   g_variant_unref (a);
4524   g_variant_unref (tuple);
4525 }
4526
4527 typedef struct {
4528   const GVariantType *type;
4529   const gchar *in;
4530   const gchar *out;
4531 } ContextTest;
4532
4533 static void
4534 test_print_context (void)
4535 {
4536   ContextTest tests[] = {
4537     { NULL, "(1, 2, 3, 'abc", "          ^^^^" },
4538     { NULL, "[1, 2, 3, 'str']", " ^        ^^^^^" },
4539     { G_VARIANT_TYPE_UINT16, "{ 'abc':'def' }", "  ^^^^^^^^^^^^^^^" },
4540     { NULL, "<5", "    ^" },
4541     { NULL, "'ab\\ux'", "  ^^^^^^^" },
4542     { NULL, "'ab\\U00efx'", "  ^^^^^^^^^^^" }
4543   };
4544   GVariant *v;
4545   gchar *s;
4546   gint i;
4547   GError *error = NULL;
4548
4549   for (i = 0; i < G_N_ELEMENTS (tests); i++)
4550     {
4551       v = g_variant_parse (tests[i].type, tests[i].in, NULL, NULL, &error);
4552       g_assert_null (v);
4553       s = g_variant_parse_error_print_context (error, tests[i].in);
4554       g_assert (strstr (s, tests[i].out) != NULL);
4555       g_free (s);
4556       g_clear_error (&error);
4557     }
4558 }
4559
4560 static void
4561 test_error_quark (void)
4562 {
4563 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
4564   g_assert (g_variant_parser_get_error_quark () == g_variant_parse_error_quark ());
4565 G_GNUC_END_IGNORE_DEPRECATIONS
4566 }
4567
4568 static void
4569 test_stack_builder_init (void)
4570 {
4571   GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE_BYTESTRING);
4572   GVariant *variant;
4573
4574   g_variant_builder_add_value (&builder, g_variant_new_byte ('g'));
4575   g_variant_builder_add_value (&builder, g_variant_new_byte ('l'));
4576   g_variant_builder_add_value (&builder, g_variant_new_byte ('i'));
4577   g_variant_builder_add_value (&builder, g_variant_new_byte ('b'));
4578   g_variant_builder_add_value (&builder, g_variant_new_byte ('\0'));
4579
4580   variant = g_variant_ref_sink (g_variant_builder_end (&builder));
4581   g_assert_nonnull (variant);
4582   g_assert (g_variant_type_equal (g_variant_get_type (variant),
4583                                   G_VARIANT_TYPE_BYTESTRING));
4584   g_assert_cmpuint (g_variant_n_children (variant), ==, 5);
4585   g_assert_cmpstr (g_variant_get_bytestring (variant), ==, "glib");
4586   g_variant_unref (variant);
4587 }
4588
4589 static GVariant *
4590 get_asv (void)
4591 {
4592   GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE_VARDICT);
4593
4594   g_variant_builder_add (&builder, "{s@v}", "foo", g_variant_new_variant (g_variant_new_string ("FOO")));
4595   g_variant_builder_add (&builder, "{s@v}", "bar", g_variant_new_variant (g_variant_new_string ("BAR")));
4596
4597   return g_variant_ref_sink (g_variant_builder_end (&builder));
4598 }
4599
4600 static void
4601 test_stack_dict_init (void)
4602 {
4603   GVariant *asv = get_asv ();
4604   GVariantDict dict = G_VARIANT_DICT_INIT (asv);
4605   GVariant *variant;
4606   GVariantIter iter;
4607   gchar *key;
4608   GVariant *value;
4609
4610   g_variant_dict_insert_value (&dict, "baz", g_variant_new_string ("BAZ"));
4611   g_variant_dict_insert_value (&dict, "quux", g_variant_new_string ("QUUX"));
4612
4613   variant = g_variant_ref_sink (g_variant_dict_end (&dict));
4614   g_assert_nonnull (variant);
4615   g_assert (g_variant_type_equal (g_variant_get_type (variant),
4616                                   G_VARIANT_TYPE_VARDICT));
4617   g_assert_cmpuint (g_variant_n_children (variant), ==, 4);
4618
4619   g_variant_iter_init (&iter, variant);
4620   while (g_variant_iter_next (&iter, "{sv}", &key, &value))
4621     {
4622       gchar *strup = g_ascii_strup (key, -1);
4623
4624       g_assert_cmpstr (strup, ==, g_variant_get_string (value, NULL));
4625       g_free (key);
4626       g_free (strup);
4627       g_variant_unref (value);
4628     }
4629
4630   g_variant_unref (asv);
4631   g_variant_unref (variant);
4632 }
4633
4634 int
4635 main (int argc, char **argv)
4636 {
4637   gint i;
4638
4639   g_test_init (&argc, &argv, NULL);
4640
4641   g_test_add_func ("/gvariant/type", test_gvarianttype);
4642   g_test_add_func ("/gvariant/typeinfo", test_gvarianttypeinfo);
4643   g_test_add_func ("/gvariant/serialiser/maybe", test_maybes);
4644   g_test_add_func ("/gvariant/serialiser/array", test_arrays);
4645   g_test_add_func ("/gvariant/serialiser/tuple", test_tuples);
4646   g_test_add_func ("/gvariant/serialiser/variant", test_variants);
4647   g_test_add_func ("/gvariant/serialiser/strings", test_strings);
4648   g_test_add_func ("/gvariant/serialiser/byteswap", test_byteswaps);
4649
4650   for (i = 1; i <= 20; i += 4)
4651     {
4652       char *testname;
4653
4654       testname = g_strdup_printf ("/gvariant/serialiser/fuzz/%d%%", i);
4655       g_test_add_data_func (testname, GINT_TO_POINTER (i),
4656                             (gpointer) test_fuzzes);
4657       g_free (testname);
4658     }
4659
4660   g_test_add_func ("/gvariant/string", test_string);
4661   g_test_add_func ("/gvariant/utf8", test_utf8);
4662   g_test_add_func ("/gvariant/containers", test_containers);
4663   g_test_add_func ("/gvariant/format-strings", test_format_strings);
4664   g_test_add_func ("/gvariant/invalid-varargs", test_invalid_varargs);
4665   g_test_add_func ("/gvariant/varargs", test_varargs);
4666   g_test_add_func ("/gvariant/varargs/subprocess/empty-array", test_varargs_empty_array);
4667   g_test_add_func ("/gvariant/valist", test_valist);
4668   g_test_add_func ("/gvariant/builder-memory", test_builder_memory);
4669   g_test_add_func ("/gvariant/hashing", test_hashing);
4670   g_test_add_func ("/gvariant/byteswap", test_gv_byteswap);
4671   g_test_add_func ("/gvariant/parser", test_parses);
4672   g_test_add_func ("/gvariant/parse-failures", test_parse_failures);
4673   g_test_add_func ("/gvariant/parse-positional", test_parse_positional);
4674   g_test_add_func ("/gvariant/parse/subprocess/bad-format-char", test_parse_bad_format_char);
4675   g_test_add_func ("/gvariant/parse/subprocess/bad-format-string", test_parse_bad_format_string);
4676   g_test_add_func ("/gvariant/parse/subprocess/bad-args", test_parse_bad_args);
4677   g_test_add_func ("/gvariant/floating", test_floating);
4678   g_test_add_func ("/gvariant/bytestring", test_bytestring);
4679   g_test_add_func ("/gvariant/lookup-value", test_lookup_value);
4680   g_test_add_func ("/gvariant/lookup", test_lookup);
4681   g_test_add_func ("/gvariant/compare", test_compare);
4682   g_test_add_func ("/gvariant/equal", test_equal);
4683   g_test_add_func ("/gvariant/fixed-array", test_fixed_array);
4684   g_test_add_func ("/gvariant/check-format-string", test_check_format_string);
4685
4686   g_test_add_func ("/gvariant/checksum-basic", test_checksum_basic);
4687   g_test_add_func ("/gvariant/checksum-nested", test_checksum_nested);
4688
4689   g_test_add_func ("/gvariant/gbytes", test_gbytes);
4690   g_test_add_func ("/gvariant/print-context", test_print_context);
4691   g_test_add_func ("/gvariant/error-quark", test_error_quark);
4692
4693   g_test_add_func ("/gvariant/stack-builder-init", test_stack_builder_init);
4694   g_test_add_func ("/gvariant/stack-dict-init", test_stack_dict_init);
4695   return g_test_run ();
4696 }