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