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