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