nexmon – Blame information for rev 1

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