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