Remove redundant header inclusions
[glib.git] / glib / tests / gvariant.c
blob7e228acac61b1eaeebf6429c91789479cd581e5f
1 /*
2 * Copyright © 2010 Codethink Limited
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.
9 * See the included COPYING file for more information.
11 * Author: Ryan Lortie <desrt@desrt.ca>
14 #include "config.h"
16 #include <glib/gvariant-internal.h>
17 #include <string.h>
18 #include <stdlib.h>
19 #include <glib.h>
21 #define BASIC "bynqiuxthdsog?"
22 #define N_BASIC (G_N_ELEMENTS (BASIC) - 1)
24 #define INVALIDS "cefjklpwz&@^$"
25 #define N_INVALIDS (G_N_ELEMENTS (INVALIDS) - 1)
27 /* see comment in gvariant-serialiser.c about this madness.
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.
35 #define ALIGN_BITS (sizeof (struct { char a; union { \
36 guint64 x; void *y; gdouble z; } b; }) - 9)
38 static gboolean
39 randomly (gdouble prob)
41 return g_test_rand_double_range (0, 1) < prob;
44 /* corecursion */
45 static GVariantType *
46 append_tuple_type_string (GString *, GString *, gboolean, gint);
48 /* append a random GVariantType to a GString
49 * append a description of the type to another GString
50 * return what the type is
52 static GVariantType *
53 append_type_string (GString *string,
54 GString *description,
55 gboolean definite,
56 gint depth)
58 if (!depth-- || randomly (0.3))
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);
64 switch (b)
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 ();
98 else
100 GVariantType *result;
102 switch (g_test_rand_int_range (0, definite ? 5 : 7))
104 case 0:
106 GVariantType *element;
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);
116 g_assert (g_variant_type_is_array (result));
117 break;
119 case 1:
121 GVariantType *element;
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);
131 g_assert (g_variant_type_is_maybe (result));
132 break;
134 case 2:
135 result = append_tuple_type_string (string, description,
136 definite, depth);
138 g_assert (g_variant_type_is_tuple (result));
139 break;
141 case 3:
143 GVariantType *key, *value;
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);
157 g_assert (g_variant_type_is_dict_entry (result));
158 break;
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;
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;
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;
181 default:
182 g_assert_not_reached ();
185 return result;
189 static GVariantType *
190 append_tuple_type_string (GString *string,
191 GString *description,
192 gboolean definite,
193 gint depth)
195 GVariantType *result, *other_result;
196 GVariantType **types;
197 gint size;
198 gint i;
200 g_string_append_c (string, '(');
201 g_string_append (description, "t of [");
203 size = g_test_rand_int_range (0, 20);
204 types = g_new (GVariantType *, size + 1);
206 for (i = 0; i < size; i++)
208 types[i] = append_type_string (string, description, definite, depth);
210 if (i < size - 1)
211 g_string_append (description, ", ");
214 types[i] = NULL;
216 g_string_append_c (description, ']');
217 g_string_append_c (string, ')');
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);
227 return result;
230 /* given a valid type string, make it invalid */
231 static gchar *
232 invalid_mutation (const gchar *type_string)
234 gboolean have_parens, have_braces;
236 /* it's valid, so '(' implies ')' and same for '{' and '}' */
237 have_parens = strchr (type_string, '(') != NULL;
238 have_braces = strchr (type_string, '{') != NULL;
240 if (have_parens && have_braces && randomly (0.3))
242 /* swap a paren and a brace */
243 gchar *pp, *bp;
244 gint np, nb;
245 gchar p, b;
246 gchar *new;
248 new = g_strdup (type_string);
250 if (randomly (0.5))
251 p = '(', b = '{';
252 else
253 p = ')', b = '}';
255 np = nb = 0;
256 pp = bp = new - 1;
258 /* count number of parens/braces */
259 while ((pp = strchr (pp + 1, p))) np++;
260 while ((bp = strchr (bp + 1, b))) nb++;
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;
266 /* find it */
267 pp = bp = new - 1;
268 while (np--) pp = strchr (pp + 1, p);
269 while (nb--) bp = strchr (bp + 1, b);
271 /* swap */
272 g_assert (*bp == b && *pp == p);
273 *bp = p;
274 *pp = b;
276 return new;
279 if ((have_parens || have_braces) && randomly (0.3))
281 /* drop a paren/brace */
282 gchar *new;
283 gchar *pp;
284 gint np;
285 gchar p;
287 if (have_parens)
288 if (randomly (0.5)) p = '('; else p = ')';
289 else
290 if (randomly (0.5)) p = '{'; else p = '}';
292 new = g_strdup (type_string);
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);
302 while (*pp)
304 *pp = *(pp + 1);
305 pp++;
308 return new;
311 /* else, perform a random mutation at a random point */
313 gint length, n;
314 gchar *new;
315 gchar p;
317 if (randomly (0.3))
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 = '}';
325 else if (randomly (0.5))
327 /* insert junk */
328 p = INVALIDS[g_test_rand_int_range (0, N_INVALIDS)];
330 else
332 /* truncate */
333 p = '\0';
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';
345 return new;
349 /* describe a type using the same language as is generated
350 * while generating the type with append_type_string
352 static gchar *
353 describe_type (const GVariantType *type)
355 gchar *result;
357 if (g_variant_type_is_container (type))
359 g_assert (!g_variant_type_is_basic (type));
361 if (g_variant_type_is_array (type))
363 gchar *subtype = describe_type (g_variant_type_element (type));
364 result = g_strdup_printf ("a of %s", subtype);
365 g_free (subtype);
367 else if (g_variant_type_is_maybe (type))
369 gchar *subtype = describe_type (g_variant_type_element (type));
370 result = g_strdup_printf ("m of %s", subtype);
371 g_free (subtype);
373 else if (g_variant_type_is_tuple (type))
375 if (!g_variant_type_equal (type, G_VARIANT_TYPE_TUPLE))
377 const GVariantType *sub;
378 GString *string;
379 gint length;
380 gint i;
382 string = g_string_new ("t of [");
384 length = g_variant_type_n_items (type);
385 sub = g_variant_type_first (type);
386 for (i = 0; i < length; i++)
388 gchar *subtype = describe_type (sub);
389 g_string_append (string, subtype);
390 g_free (subtype);
392 if ((sub = g_variant_type_next (sub)))
393 g_string_append (string, ", ");
395 g_assert (sub == NULL);
396 g_string_append_c (string, ']');
398 result = g_string_free (string, FALSE);
400 else
401 result = g_strdup ("R");
403 else if (g_variant_type_is_dict_entry (type))
405 gchar *key, *value, *key2, *value2;
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);
422 else if (g_variant_type_equal (type, G_VARIANT_TYPE_VARIANT))
424 result = g_strdup ("V");
426 else
427 g_assert_not_reached ();
429 else
431 if (g_variant_type_is_definite (type))
433 g_assert (g_variant_type_is_basic (type));
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 ();
464 else
466 if (g_variant_type_equal (type, G_VARIANT_TYPE_ANY))
468 result = g_strdup ("S");
470 else if (g_variant_type_equal (type, G_VARIANT_TYPE_BASIC))
472 result = g_strdup ("?");
474 else
475 g_assert_not_reached ();
479 return result;
482 /* given a type string, replace one of the indefinite type characters in
483 * it with a matching type (possibly the same type).
485 static gchar *
486 generate_subtype (const gchar *type_string)
488 GVariantType *replacement;
489 GString *result, *junk;
490 gint length, n = 0, l;
492 result = g_string_new (NULL);
493 junk = g_string_new (NULL);
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) */
502 /* pick one at random to replace */
503 n = g_test_rand_int_range (0, n) + 1;
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] == '*');
512 /* store up to that point in a GString */
513 g_string_append_len (result, type_string, l);
515 /* then store the replacement in the GString */
516 if (type_string[l] == 'r')
517 replacement = append_tuple_type_string (result, junk, FALSE, 3);
519 else if (type_string[l] == '?')
520 replacement = append_type_string (result, junk, FALSE, 0);
522 else if (type_string[l] == '*')
523 replacement = append_type_string (result, junk, FALSE, 3);
525 else
526 g_assert_not_reached ();
528 /* ensure the replacement has the proper type */
529 g_assert (g_variant_type_is_subtype_of (replacement,
530 (gpointer) &type_string[l]));
532 /* store the rest from the original type string */
533 g_string_append (result, type_string + l + 1);
535 g_variant_type_free (replacement);
536 g_string_free (junk, TRUE);
538 return g_string_free (result, FALSE);
541 struct typestack
543 const GVariantType *type;
544 struct typestack *parent;
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.
551 static void
552 subtype_check (const gchar *type_string,
553 struct typestack *parent_ts)
555 struct typestack ts, *node;
556 gchar *subtype;
557 gint depth = 0;
559 subtype = generate_subtype (type_string);
561 ts.type = G_VARIANT_TYPE (subtype);
562 ts.parent = parent_ts;
564 for (node = &ts; node; node = node->parent)
566 /* this type should be a subtype of each parent type */
567 g_assert (g_variant_type_is_subtype_of (ts.type, node->type));
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));
573 depth++;
576 if (!g_variant_type_is_definite (ts.type) && depth < 5)
578 /* the type is still indefinite and we haven't repeated too many
579 * times. go once more.
582 subtype_check (subtype, &ts);
585 g_free (subtype);
588 static void
589 test_gvarianttype (void)
591 gint i;
593 for (i = 0; i < 2000; i++)
595 GString *type_string, *description;
596 GVariantType *type, *other_type;
597 const GVariantType *ctype;
598 gchar *invalid;
599 gchar *desc;
601 type_string = g_string_new (NULL);
602 description = g_string_new (NULL);
604 /* generate a random type, its type string and a description
606 * exercises type constructor functions and g_variant_type_copy()
608 type = append_type_string (type_string, description, FALSE, 6);
610 /* convert the type string to a type and ensure that it is equal
611 * to the one produced with the type constructor routines
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));
619 /* check if the type is indefinite */
620 if (!g_variant_type_is_definite (type))
622 struct typestack ts = { type, NULL };
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.
628 subtype_check (type_string->str, &ts);
630 else
631 /* ensure that no indefinite characters appear */
632 g_assert (strcspn (type_string->str, "r?*") == type_string->len);
635 /* describe the type.
637 * exercises the type iterator interface
639 desc = describe_type (type);
641 /* make sure the description matches */
642 g_assert_cmpstr (desc, ==, description->str);
643 g_free (desc);
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);
652 /* concatenate another type to the type string and ensure that
653 * the result is recognised as being invalid
655 other_type = append_type_string (type_string, description, FALSE, 2);
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);
664 #define ALIGNED(x, y) (((x + (y - 1)) / y) * y)
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.
670 static void
671 calculate_type_info (const GVariantType *type,
672 gsize *fixed_size,
673 guint *alignment)
675 if (g_variant_type_is_array (type) ||
676 g_variant_type_is_maybe (type))
678 calculate_type_info (g_variant_type_element (type), NULL, alignment);
680 if (fixed_size)
681 *fixed_size = 0;
683 else if (g_variant_type_is_tuple (type) ||
684 g_variant_type_is_dict_entry (type))
686 if (g_variant_type_n_items (type))
688 const GVariantType *sub;
689 gboolean variable;
690 gsize size;
691 guint al;
693 variable = FALSE;
694 size = 0;
695 al = 0;
697 sub = g_variant_type_first (type);
700 gsize this_fs;
701 guint this_al;
703 calculate_type_info (sub, &this_fs, &this_al);
705 al = MAX (al, this_al);
707 if (!this_fs)
709 variable = TRUE;
710 size = 0;
713 if (!variable)
715 size = ALIGNED (size, this_al);
716 size += this_fs;
719 while ((sub = g_variant_type_next (sub)));
721 size = ALIGNED (size, al);
723 if (alignment)
724 *alignment = al;
726 if (fixed_size)
727 *fixed_size = size;
729 else
731 if (fixed_size)
732 *fixed_size = 1;
734 if (alignment)
735 *alignment = 1;
738 else
740 gint fs, al;
742 if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN) ||
743 g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
745 al = fs = 1;
748 else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT16) ||
749 g_variant_type_equal (type, G_VARIANT_TYPE_UINT16))
751 al = fs = 2;
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))
758 al = fs = 4;
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))
765 al = fs = 8;
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))
771 al = 1;
772 fs = 0;
774 else if (g_variant_type_equal (type, G_VARIANT_TYPE_VARIANT))
776 al = 8;
777 fs = 0;
779 else
780 g_assert_not_reached ();
782 if (fixed_size)
783 *fixed_size = fs;
785 if (alignment)
786 *alignment = al;
790 /* same as the describe_type() function above, but iterates over
791 * typeinfo instead of types.
793 static gchar *
794 describe_info (GVariantTypeInfo *info)
796 gchar *result;
798 switch (g_variant_type_info_get_type_char (info))
800 case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
802 gchar *element;
804 element = describe_info (g_variant_type_info_element (info));
805 result = g_strdup_printf ("m of %s", element);
806 g_free (element);
808 break;
810 case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
812 gchar *element;
814 element = describe_info (g_variant_type_info_element (info));
815 result = g_strdup_printf ("a of %s", element);
816 g_free (element);
818 break;
820 case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
822 const gchar *sep = "";
823 GString *string;
824 gint length;
825 gint i;
827 string = g_string_new ("t of [");
828 length = g_variant_type_info_n_members (info);
830 for (i = 0; i < length; i++)
832 const GVariantMemberInfo *minfo;
833 gchar *subtype;
835 g_string_append (string, sep);
836 sep = ", ";
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);
844 g_string_append_c (string, ']');
846 result = g_string_free (string, FALSE);
848 break;
850 case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
852 const GVariantMemberInfo *keyinfo, *valueinfo;
853 gchar *key, *value;
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);
864 break;
866 case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
867 result = g_strdup ("V");
868 break;
870 default:
871 result = g_strdup (g_variant_type_info_get_type_string (info));
872 g_assert_cmpint (strlen (result), ==, 1);
873 break;
876 return result;
879 /* check that the O(1) method of calculating offsets meshes with the
880 * results of simple iteration.
882 static void
883 check_offsets (GVariantTypeInfo *info,
884 const GVariantType *type)
886 gint flavour;
887 gint length;
889 length = g_variant_type_info_n_members (info);
890 g_assert_cmpint (length, ==, g_variant_type_n_items (type));
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.
896 for (flavour = 0; flavour < 8; flavour++)
898 const GVariantType *subtype;
899 gsize last_offset_index;
900 gsize last_offset;
901 gsize position;
902 gint i;
904 subtype = g_variant_type_first (type);
905 last_offset_index = -1;
906 last_offset = 0;
907 position = 0;
909 /* go through the tuple, keeping track of our position */
910 for (i = 0; i < length; i++)
912 gsize fixed_size;
913 guint alignment;
915 calculate_type_info (subtype, &fixed_size, &alignment);
917 position = ALIGNED (position, alignment);
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
924 const GVariantMemberInfo *member;
925 gsize start;
927 member = g_variant_type_info_member_info (info, i);
928 g_assert_cmpint (member->i, ==, last_offset_index);
930 /* do the calculation using the typeinfo */
931 start = last_offset;
932 start += member->a;
933 start &= member->b;
934 start |= member->c;
936 /* did we reach the same spot? */
937 g_assert_cmpint (start, ==, position);
940 if (fixed_size)
942 /* fixed size. add that size. */
943 position += fixed_size;
945 else
947 /* variable size. do the flavouring. */
948 while ((position & 0x7) != flavour)
949 position++;
951 /* and store the offset, just like it would be in the
952 * serialised data.
954 last_offset = position;
955 last_offset_index++;
958 /* next type */
959 subtype = g_variant_type_next (subtype);
962 /* make sure we used up exactly all the types */
963 g_assert (subtype == NULL);
967 static void
968 test_gvarianttypeinfo (void)
970 gint i;
972 for (i = 0; i < 2000; i++)
974 GString *type_string, *description;
975 gsize fixed_size1, fixed_size2;
976 guint alignment1, alignment2;
977 GVariantTypeInfo *info;
978 GVariantType *type;
979 gchar *desc;
981 type_string = g_string_new (NULL);
982 description = g_string_new (NULL);
984 /* random type */
985 type = append_type_string (type_string, description, TRUE, 6);
987 /* create a typeinfo for it */
988 info = g_variant_type_info_get (type);
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);
994 /* calculate the alignment and fixed size, compare to the
995 * typeinfo's calculations
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);
1002 /* test the iteration functions over typeinfo structures by
1003 * "describing" the typeinfo and verifying equality.
1005 desc = describe_info (info);
1006 g_assert_cmpstr (desc, ==, description->str);
1008 /* do extra checks for containers */
1009 if (g_variant_type_is_array (type) ||
1010 g_variant_type_is_maybe (type))
1012 const GVariantType *element;
1013 gsize efs1, efs2;
1014 guint ea1, ea2;
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);
1022 g_assert_cmpint (ea1, ==, alignment1);
1023 g_assert_cmpint (0, ==, fixed_size1);
1025 else if (g_variant_type_is_tuple (type) ||
1026 g_variant_type_is_dict_entry (type))
1028 /* make sure the "magic constants" are working */
1029 check_offsets (info, type);
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);
1039 g_variant_type_info_assert_no_infos ();
1042 #define MAX_FIXED_MULTIPLIER 256
1043 #define MAX_INSTANCE_SIZE 1024
1044 #define MAX_ARRAY_CHILDREN 128
1045 #define MAX_TUPLE_CHILDREN 128
1047 /* this function generates a random type such that all characteristics
1048 * that are "interesting" to the serialiser are tested.
1050 * this basically means:
1051 * - test different alignments
1052 * - test variable sized items and fixed sized items
1053 * - test different fixed sizes
1055 static gchar *
1056 random_type_string (void)
1058 const guchar base_types[] = "ynix";
1059 guchar base_type;
1061 base_type = base_types[g_test_rand_int_range (0, 4)];
1063 if (g_test_rand_bit ())
1064 /* construct a fixed-sized type */
1066 char type_string[MAX_FIXED_MULTIPLIER];
1067 guint multiplier;
1068 guint i = 0;
1070 multiplier = g_test_rand_int_range (1, sizeof type_string - 1);
1072 type_string[i++] = '(';
1073 while (multiplier--)
1074 type_string[i++] = base_type;
1075 type_string[i++] = ')';
1077 return g_strndup (type_string, i);
1079 else
1080 /* construct a variable-sized type */
1082 char type_string[2] = { 'a', base_type };
1084 return g_strndup (type_string, 2);
1088 typedef struct
1090 GVariantTypeInfo *type_info;
1091 guint alignment;
1092 gsize size;
1093 gboolean is_fixed_sized;
1095 guint32 seed;
1097 #define INSTANCE_MAGIC 1287582829
1098 guint magic;
1099 } RandomInstance;
1101 static RandomInstance *
1102 random_instance (GVariantTypeInfo *type_info)
1104 RandomInstance *instance;
1106 instance = g_slice_new (RandomInstance);
1108 if (type_info == NULL)
1110 gchar *str = random_type_string ();
1111 instance->type_info = g_variant_type_info_get (G_VARIANT_TYPE (str));
1112 g_free (str);
1114 else
1115 instance->type_info = g_variant_type_info_ref (type_info);
1117 instance->seed = g_test_rand_int ();
1119 g_variant_type_info_query (instance->type_info,
1120 &instance->alignment,
1121 &instance->size);
1123 instance->is_fixed_sized = instance->size != 0;
1125 if (!instance->is_fixed_sized)
1126 instance->size = g_test_rand_int_range (0, MAX_INSTANCE_SIZE);
1128 instance->magic = INSTANCE_MAGIC;
1130 return instance;
1133 static void
1134 random_instance_free (RandomInstance *instance)
1136 g_variant_type_info_unref (instance->type_info);
1137 g_slice_free (RandomInstance, instance);
1140 static void
1141 append_instance_size (RandomInstance *instance,
1142 gsize *offset)
1144 *offset += (-*offset) & instance->alignment;
1145 *offset += instance->size;
1148 static void
1149 random_instance_write (RandomInstance *instance,
1150 guchar *buffer)
1152 GRand *rand;
1153 gint i;
1155 g_assert_cmpint ((gsize) buffer & ALIGN_BITS & instance->alignment, ==, 0);
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);
1163 static void
1164 append_instance_data (RandomInstance *instance,
1165 guchar **buffer)
1167 while (((gsize) *buffer) & instance->alignment)
1168 *(*buffer)++ = '\0';
1170 random_instance_write (instance, *buffer);
1171 *buffer += instance->size;
1174 static gboolean
1175 random_instance_assert (RandomInstance *instance,
1176 guchar *buffer,
1177 gsize size)
1179 GRand *rand;
1180 gint i;
1182 g_assert_cmpint ((gsize) buffer & ALIGN_BITS & instance->alignment, ==, 0);
1183 g_assert_cmpint (size, ==, instance->size);
1185 rand = g_rand_new_with_seed (instance->seed);
1186 for (i = 0; i < instance->size; i++)
1188 guchar byte = g_rand_int (rand);
1190 g_assert (buffer[i] == byte);
1192 g_rand_free (rand);
1194 return i == instance->size;
1197 static gboolean
1198 random_instance_check (RandomInstance *instance,
1199 guchar *buffer,
1200 gsize size)
1202 GRand *rand;
1203 gint i;
1205 g_assert_cmpint ((gsize) buffer & ALIGN_BITS & instance->alignment, ==, 0);
1207 if (size != instance->size)
1208 return FALSE;
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);
1216 return i == instance->size;
1219 static void
1220 random_instance_filler (GVariantSerialised *serialised,
1221 gpointer data)
1223 RandomInstance *instance = data;
1225 g_assert (instance->magic == INSTANCE_MAGIC);
1227 if (serialised->type_info == NULL)
1228 serialised->type_info = instance->type_info;
1230 if (serialised->size == 0)
1231 serialised->size = instance->size;
1233 g_assert (serialised->type_info == instance->type_info);
1234 g_assert (serialised->size == instance->size);
1236 if (serialised->data)
1237 random_instance_write (instance, serialised->data);
1240 static gsize
1241 calculate_offset_size (gsize body_size,
1242 gsize n_offsets)
1244 if (body_size == 0)
1245 return 0;
1247 if (body_size + n_offsets <= G_MAXUINT8)
1248 return 1;
1250 if (body_size + 2 * n_offsets <= G_MAXUINT16)
1251 return 2;
1253 if (body_size + 4 * n_offsets <= G_MAXUINT32)
1254 return 4;
1256 /* the test case won't generate anything bigger */
1257 g_assert_not_reached ();
1260 static gpointer
1261 flavoured_malloc (gsize size, gsize flavour)
1263 g_assert (flavour < 8);
1265 if (size == 0)
1266 return NULL;
1268 return ((gchar *) g_malloc (size + flavour)) + flavour;
1271 static void
1272 flavoured_free (gpointer data,
1273 gsize flavour)
1275 if (!data)
1276 return;
1277 g_free (((gchar *) data) - flavour);
1280 static gpointer
1281 align_malloc (gsize size)
1283 gpointer mem;
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.
1293 mem = malloc (size);
1294 #endif
1296 return mem;
1299 static void
1300 align_free (gpointer mem)
1302 free (mem);
1305 static void
1306 append_offset (guchar **offset_ptr,
1307 gsize offset,
1308 guint offset_size)
1310 union
1312 guchar bytes[sizeof (gsize)];
1313 gsize integer;
1314 } tmpvalue;
1316 tmpvalue.integer = GSIZE_TO_LE (offset);
1317 memcpy (*offset_ptr, tmpvalue.bytes, offset_size);
1318 *offset_ptr += offset_size;
1321 static void
1322 prepend_offset (guchar **offset_ptr,
1323 gsize offset,
1324 guint offset_size)
1326 union
1328 guchar bytes[sizeof (gsize)];
1329 gsize integer;
1330 } tmpvalue;
1332 *offset_ptr -= offset_size;
1333 tmpvalue.integer = GSIZE_TO_LE (offset);
1334 memcpy (*offset_ptr, tmpvalue.bytes, offset_size);
1337 static void
1338 test_maybe (void)
1340 GVariantTypeInfo *type_info;
1341 RandomInstance *instance;
1342 gsize needed_size;
1343 guchar *data;
1345 instance = random_instance (NULL);
1348 const gchar *element;
1349 gchar *tmp;
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);
1357 needed_size = g_variant_serialiser_needed_size (type_info,
1358 random_instance_filler,
1359 NULL, 0);
1360 g_assert_cmpint (needed_size, ==, 0);
1362 needed_size = g_variant_serialiser_needed_size (type_info,
1363 random_instance_filler,
1364 (gpointer *) &instance, 1);
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);
1372 guchar *ptr;
1374 ptr = data = align_malloc (needed_size);
1375 append_instance_data (instance, &ptr);
1377 if (!instance->is_fixed_sized)
1378 *ptr++ = '\0';
1380 g_assert_cmpint (ptr - data, ==, needed_size);
1384 guint alignment;
1385 guint flavour;
1387 alignment = (instance->alignment & ALIGN_BITS) + 1;
1389 for (flavour = 0; flavour < 8; flavour += alignment)
1391 GVariantSerialised serialised;
1392 GVariantSerialised child;
1394 serialised.type_info = type_info;
1395 serialised.data = flavoured_malloc (needed_size, flavour);
1396 serialised.size = needed_size;
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);
1409 g_variant_type_info_unref (type_info);
1410 random_instance_free (instance);
1411 align_free (data);
1414 static void
1415 test_maybes (void)
1417 guint i;
1419 for (i = 0; i < 1000; i++)
1420 test_maybe ();
1422 g_variant_type_info_assert_no_infos ();
1425 static void
1426 test_array (void)
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;
1437 gchar *element_type, *array_type;
1439 element_type = random_type_string ();
1440 array_type = g_strdup_printf ("a%s", element_type);
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);
1446 g_free (element_type);
1447 g_free (array_type);
1451 guint i;
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);
1459 needed_size = g_variant_serialiser_needed_size (array_info,
1460 random_instance_filler,
1461 (gpointer *) instances,
1462 n_children);
1465 gsize element_fixed_size;
1466 gsize body_size = 0;
1467 guint i;
1469 for (i = 0; i < n_children; i++)
1470 append_instance_size (instances[i], &body_size);
1472 g_variant_type_info_query (element_info, NULL, &element_fixed_size);
1474 if (!element_fixed_size)
1476 offset_size = calculate_offset_size (body_size, n_children);
1478 if (offset_size == 0)
1479 offset_size = 1;
1481 else
1482 offset_size = 0;
1484 g_assert_cmpint (needed_size, ==, body_size + n_children * offset_size);
1488 guchar *offset_ptr, *body_ptr;
1489 guint i;
1491 body_ptr = data = align_malloc (needed_size);
1492 offset_ptr = body_ptr + needed_size - offset_size * n_children;
1494 for (i = 0; i < n_children; i++)
1496 append_instance_data (instances[i], &body_ptr);
1497 append_offset (&offset_ptr, body_ptr - data, offset_size);
1500 g_assert (body_ptr == data + needed_size - offset_size * n_children);
1501 g_assert (offset_ptr == data + needed_size);
1505 guint alignment;
1506 gsize flavour;
1507 guint i;
1509 g_variant_type_info_query (array_info, &alignment, NULL);
1510 alignment = (alignment & ALIGN_BITS) + 1;
1512 for (flavour = 0; flavour < 8; flavour += alignment)
1514 GVariantSerialised serialised;
1516 serialised.type_info = array_info;
1517 serialised.data = flavoured_malloc (needed_size, flavour);
1518 serialised.size = needed_size;
1520 g_variant_serialiser_serialise (serialised, random_instance_filler,
1521 (gpointer *) instances, n_children);
1523 g_assert (memcmp (serialised.data, data, serialised.size) == 0);
1524 g_assert (g_variant_serialised_n_children (serialised) == n_children);
1526 for (i = 0; i < n_children; i++)
1528 GVariantSerialised child;
1530 child = g_variant_serialised_get_child (serialised, i);
1531 g_assert (child.type_info == instances[i]->type_info);
1532 random_instance_assert (instances[i], child.data, child.size);
1533 g_variant_type_info_unref (child.type_info);
1536 flavoured_free (serialised.data, flavour);
1541 guint i;
1543 for (i = 0; i < n_children; i++)
1544 random_instance_free (instances[i]);
1545 g_free (instances);
1548 g_variant_type_info_unref (element_info);
1549 g_variant_type_info_unref (array_info);
1550 align_free (data);
1553 static void
1554 test_arrays (void)
1556 guint i;
1558 for (i = 0; i < 100; i++)
1559 test_array ();
1561 g_variant_type_info_assert_no_infos ();
1564 static void
1565 test_tuple (void)
1567 GVariantTypeInfo *type_info;
1568 RandomInstance **instances;
1569 gboolean fixed_size;
1570 gsize needed_size;
1571 gsize offset_size;
1572 guint n_children;
1573 guint alignment;
1574 guchar *data;
1576 n_children = g_test_rand_int_range (0, MAX_TUPLE_CHILDREN);
1577 instances = g_new (RandomInstance *, n_children);
1580 GString *type_string;
1581 guint i;
1583 fixed_size = TRUE;
1584 alignment = 0;
1586 type_string = g_string_new ("(");
1587 for (i = 0; i < n_children; i++)
1589 const gchar *str;
1591 instances[i] = random_instance (NULL);
1593 alignment |= instances[i]->alignment;
1594 if (!instances[i]->is_fixed_sized)
1595 fixed_size = FALSE;
1597 str = g_variant_type_info_get_type_string (instances[i]->type_info);
1598 g_string_append (type_string, str);
1600 g_string_append_c (type_string, ')');
1602 type_info = g_variant_type_info_get (G_VARIANT_TYPE (type_string->str));
1603 g_string_free (type_string, TRUE);
1606 needed_size = g_variant_serialiser_needed_size (type_info,
1607 random_instance_filler,
1608 (gpointer *) instances,
1609 n_children);
1611 gsize body_size = 0;
1612 gsize offsets = 0;
1613 guint i;
1615 for (i = 0; i < n_children; i++)
1617 append_instance_size (instances[i], &body_size);
1619 if (i != n_children - 1 && !instances[i]->is_fixed_sized)
1620 offsets++;
1623 if (fixed_size)
1625 body_size += (-body_size) & alignment;
1627 g_assert ((body_size == 0) == (n_children == 0));
1628 if (n_children == 0)
1629 body_size = 1;
1632 offset_size = calculate_offset_size (body_size, offsets);
1633 g_assert_cmpint (needed_size, ==, body_size + offsets * offset_size);
1637 guchar *body_ptr;
1638 guchar *ofs_ptr;
1639 guint i;
1641 body_ptr = data = align_malloc (needed_size);
1642 ofs_ptr = body_ptr + needed_size;
1644 for (i = 0; i < n_children; i++)
1646 append_instance_data (instances[i], &body_ptr);
1648 if (i != n_children - 1 && !instances[i]->is_fixed_sized)
1649 prepend_offset (&ofs_ptr, body_ptr - data, offset_size);
1652 if (fixed_size)
1654 while (((gsize) body_ptr) & alignment)
1655 *body_ptr++ = '\0';
1657 g_assert ((body_ptr == data) == (n_children == 0));
1658 if (n_children == 0)
1659 *body_ptr++ = '\0';
1664 g_assert (body_ptr == ofs_ptr);
1668 gsize flavour;
1669 guint i;
1671 alignment = (alignment & ALIGN_BITS) + 1;
1673 for (flavour = 0; flavour < 8; flavour += alignment)
1675 GVariantSerialised serialised;
1677 serialised.type_info = type_info;
1678 serialised.data = flavoured_malloc (needed_size, flavour);
1679 serialised.size = needed_size;
1681 g_variant_serialiser_serialise (serialised, random_instance_filler,
1682 (gpointer *) instances, n_children);
1684 g_assert (memcmp (serialised.data, data, serialised.size) == 0);
1685 g_assert (g_variant_serialised_n_children (serialised) == n_children);
1687 for (i = 0; i < n_children; i++)
1689 GVariantSerialised child;
1691 child = g_variant_serialised_get_child (serialised, i);
1692 g_assert (child.type_info == instances[i]->type_info);
1693 random_instance_assert (instances[i], child.data, child.size);
1694 g_variant_type_info_unref (child.type_info);
1697 flavoured_free (serialised.data, flavour);
1702 guint i;
1704 for (i = 0; i < n_children; i++)
1705 random_instance_free (instances[i]);
1706 g_free (instances);
1709 g_variant_type_info_unref (type_info);
1710 align_free (data);
1713 static void
1714 test_tuples (void)
1716 guint i;
1718 for (i = 0; i < 100; i++)
1719 test_tuple ();
1721 g_variant_type_info_assert_no_infos ();
1724 static void
1725 test_variant (void)
1727 GVariantTypeInfo *type_info;
1728 RandomInstance *instance;
1729 const gchar *type_string;
1730 gsize needed_size;
1731 guchar *data;
1732 gsize len;
1734 type_info = g_variant_type_info_get (G_VARIANT_TYPE_VARIANT);
1735 instance = random_instance (NULL);
1737 type_string = g_variant_type_info_get_type_string (instance->type_info);
1738 len = strlen (type_string);
1740 needed_size = g_variant_serialiser_needed_size (type_info,
1741 random_instance_filler,
1742 (gpointer *) &instance, 1);
1744 g_assert_cmpint (needed_size, ==, instance->size + 1 + len);
1747 guchar *ptr;
1749 ptr = data = align_malloc (needed_size);
1750 append_instance_data (instance, &ptr);
1751 *ptr++ = '\0';
1752 memcpy (ptr, type_string, len);
1753 ptr += len;
1755 g_assert (data + needed_size == ptr);
1759 gsize alignment;
1760 gsize flavour;
1762 /* variants are always 8-aligned */
1763 alignment = ALIGN_BITS + 1;
1765 for (flavour = 0; flavour < 8; flavour += alignment)
1767 GVariantSerialised serialised;
1768 GVariantSerialised child;
1770 serialised.type_info = type_info;
1771 serialised.data = flavoured_malloc (needed_size, flavour);
1772 serialised.size = needed_size;
1774 g_variant_serialiser_serialise (serialised, random_instance_filler,
1775 (gpointer *) &instance, 1);
1777 g_assert (memcmp (serialised.data, data, serialised.size) == 0);
1778 g_assert (g_variant_serialised_n_children (serialised) == 1);
1780 child = g_variant_serialised_get_child (serialised, 0);
1781 g_assert (child.type_info == instance->type_info);
1782 random_instance_check (instance, child.data, child.size);
1784 g_variant_type_info_unref (child.type_info);
1785 flavoured_free (serialised.data, flavour);
1789 g_variant_type_info_unref (type_info);
1790 random_instance_free (instance);
1791 align_free (data);
1794 static void
1795 test_variants (void)
1797 guint i;
1799 for (i = 0; i < 100; i++)
1800 test_variant ();
1802 g_variant_type_info_assert_no_infos ();
1805 static void
1806 test_strings (void)
1808 struct {
1809 guint flags;
1810 guint size;
1811 gconstpointer data;
1812 } test_cases[] = {
1813 #define is_nval 0
1814 #define is_string 1
1815 #define is_objpath is_string | 2
1816 #define is_sig is_string | 4
1817 { is_sig, 1, "" },
1818 { is_nval, 0, NULL },
1819 { is_nval, 13, "hello\xffworld!" },
1820 { is_string, 13, "hello world!" },
1821 { is_nval, 13, "hello world\0" },
1822 { is_nval, 13, "hello\0world!" },
1823 { is_nval, 12, "hello world!" },
1825 { is_objpath, 2, "/" },
1826 { is_objpath, 3, "/a" },
1827 { is_string, 3, "//" },
1828 { is_objpath, 11, "/some/path" },
1829 { is_string, 12, "/some/path/" },
1830 { is_nval, 11, "/some\0path" },
1831 { is_string, 11, "/some\\path" },
1832 { is_string, 12, "/some//path" },
1833 { is_string, 12, "/some-/path" },
1835 { is_sig, 2, "i" },
1836 { is_sig, 2, "s" },
1837 { is_sig, 5, "(si)" },
1838 { is_string, 4, "(si" },
1839 { is_string, 2, "*" },
1840 { is_sig, 3, "ai" },
1841 { is_string, 3, "mi" },
1842 { is_string, 2, "r" },
1843 { is_sig, 15, "(yyy{sv}ssiai)" },
1844 { is_string, 16, "(yyy{yv}ssiai))" },
1845 { is_string, 15, "(yyy{vv}ssiai)" },
1846 { is_string, 15, "(yyy{sv)ssiai}" }
1848 guint i;
1850 for (i = 0; i < G_N_ELEMENTS (test_cases); i++)
1852 guint flags;
1854 flags = g_variant_serialiser_is_string (test_cases[i].data,
1855 test_cases[i].size)
1856 ? 1 : 0;
1858 flags |= g_variant_serialiser_is_object_path (test_cases[i].data,
1859 test_cases[i].size)
1860 ? 2 : 0;
1862 flags |= g_variant_serialiser_is_signature (test_cases[i].data,
1863 test_cases[i].size)
1864 ? 4 : 0;
1866 g_assert (flags == test_cases[i].flags);
1870 typedef struct _TreeInstance TreeInstance;
1871 struct _TreeInstance
1873 GVariantTypeInfo *info;
1875 TreeInstance **children;
1876 gsize n_children;
1878 union {
1879 guint64 integer;
1880 gdouble floating;
1881 gchar string[32];
1882 } data;
1883 gsize data_size;
1886 static GVariantType *
1887 make_random_definite_type (int depth)
1889 GString *description;
1890 GString *type_string;
1891 GVariantType *type;
1893 description = g_string_new (NULL);
1894 type_string = g_string_new (NULL);
1895 type = append_type_string (type_string, description, TRUE, depth);
1896 g_string_free (description, TRUE);
1897 g_string_free (type_string, TRUE);
1899 return type;
1902 static void
1903 make_random_string (gchar *string,
1904 gsize size,
1905 const GVariantType *type)
1907 gint i;
1909 /* create strings that are valid signature strings */
1910 #define good_chars "bynqiuxthdsog"
1912 for (i = 0; i < size - 1; i++)
1913 string[i] = good_chars[g_test_rand_int_range (0, strlen (good_chars))];
1914 string[i] = '\0';
1916 /* in case we need an object path, prefix a '/' */
1917 if (*g_variant_type_peek_string (type) == 'o')
1918 string[0] = '/';
1920 #undef good_chars
1923 static TreeInstance *
1924 tree_instance_new (const GVariantType *type,
1925 int depth)
1927 const GVariantType *child_type = NULL;
1928 GVariantType *mytype = NULL;
1929 TreeInstance *instance;
1930 gboolean is_tuple_type;
1932 if (type == NULL)
1933 type = mytype = make_random_definite_type (depth);
1935 instance = g_slice_new (TreeInstance);
1936 instance->info = g_variant_type_info_get (type);
1937 instance->children = NULL;
1938 instance->n_children = 0;
1939 instance->data_size = 0;
1941 is_tuple_type = FALSE;
1943 switch (*g_variant_type_peek_string (type))
1945 case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
1946 instance->n_children = g_test_rand_int_range (0, 2);
1947 child_type = g_variant_type_element (type);
1948 break;
1950 case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
1951 instance->n_children = g_test_rand_int_range (0, MAX_ARRAY_CHILDREN);
1952 child_type = g_variant_type_element (type);
1953 break;
1955 case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
1956 case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
1957 instance->n_children = g_variant_type_n_items (type);
1958 child_type = g_variant_type_first (type);
1959 is_tuple_type = TRUE;
1960 break;
1962 case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
1963 instance->n_children = 1;
1964 child_type = NULL;
1965 break;
1967 case 'b':
1968 instance->data.integer = g_test_rand_int_range (0, 2);
1969 instance->data_size = 1;
1970 break;
1972 case 'y':
1973 instance->data.integer = g_test_rand_int ();
1974 instance->data_size = 1;
1975 break;
1977 case 'n': case 'q':
1978 instance->data.integer = g_test_rand_int ();
1979 instance->data_size = 2;
1980 break;
1982 case 'i': case 'u': case 'h':
1983 instance->data.integer = g_test_rand_int ();
1984 instance->data_size = 4;
1985 break;
1987 case 'x': case 't':
1988 instance->data.integer = g_test_rand_int ();
1989 instance->data.integer <<= 32;
1990 instance->data.integer |= (guint32) g_test_rand_int ();
1991 instance->data_size = 8;
1992 break;
1994 case 'd':
1995 instance->data.floating = g_test_rand_double ();
1996 instance->data_size = 8;
1997 break;
1999 case 's': case 'o': case 'g':
2000 instance->data_size = g_test_rand_int_range (10, 20);
2001 make_random_string (instance->data.string, instance->data_size, type);
2002 break;
2005 if (instance->data_size == 0)
2006 /* no data -> it is a container */
2008 guint i;
2010 instance->children = g_new (TreeInstance *, instance->n_children);
2012 for (i = 0; i < instance->n_children; i++)
2014 instance->children[i] = tree_instance_new (child_type, depth - 1);
2016 if (is_tuple_type)
2017 child_type = g_variant_type_next (child_type);
2020 g_assert (!is_tuple_type || child_type == NULL);
2023 g_variant_type_free (mytype);
2025 return instance;
2028 static void
2029 tree_instance_free (TreeInstance *instance)
2031 gint i;
2033 g_variant_type_info_unref (instance->info);
2034 for (i = 0; i < instance->n_children; i++)
2035 tree_instance_free (instance->children[i]);
2036 g_free (instance->children);
2037 g_slice_free (TreeInstance, instance);
2040 static gboolean i_am_writing_byteswapped;
2042 static void
2043 tree_filler (GVariantSerialised *serialised,
2044 gpointer data)
2046 TreeInstance *instance = data;
2048 if (serialised->type_info == NULL)
2049 serialised->type_info = instance->info;
2051 if (instance->data_size == 0)
2052 /* is a container */
2054 if (serialised->size == 0)
2055 serialised->size =
2056 g_variant_serialiser_needed_size (instance->info, tree_filler,
2057 (gpointer *) instance->children,
2058 instance->n_children);
2060 if (serialised->data)
2061 g_variant_serialiser_serialise (*serialised, tree_filler,
2062 (gpointer *) instance->children,
2063 instance->n_children);
2065 else
2066 /* it is a leaf */
2068 if (serialised->size == 0)
2069 serialised->size = instance->data_size;
2071 if (serialised->data)
2073 switch (instance->data_size)
2075 case 1:
2076 *serialised->data = instance->data.integer;
2077 break;
2079 case 2:
2081 guint16 value = instance->data.integer;
2083 if (i_am_writing_byteswapped)
2084 value = GUINT16_SWAP_LE_BE (value);
2086 *(guint16 *) serialised->data = value;
2088 break;
2090 case 4:
2092 guint32 value = instance->data.integer;
2094 if (i_am_writing_byteswapped)
2095 value = GUINT32_SWAP_LE_BE (value);
2097 *(guint32 *) serialised->data = value;
2099 break;
2101 case 8:
2103 guint64 value = instance->data.integer;
2105 if (i_am_writing_byteswapped)
2106 value = GUINT64_SWAP_LE_BE (value);
2108 *(guint64 *) serialised->data = value;
2110 break;
2112 default:
2113 memcpy (serialised->data,
2114 instance->data.string,
2115 instance->data_size);
2116 break;
2122 static gboolean
2123 check_tree (TreeInstance *instance,
2124 GVariantSerialised serialised)
2126 if (instance->info != serialised.type_info)
2127 return FALSE;
2129 if (instance->data_size == 0)
2130 /* is a container */
2132 gint i;
2134 if (g_variant_serialised_n_children (serialised) !=
2135 instance->n_children)
2136 return FALSE;
2138 for (i = 0; i < instance->n_children; i++)
2140 GVariantSerialised child;
2141 gpointer data = NULL;
2142 gboolean ok;
2144 child = g_variant_serialised_get_child (serialised, i);
2145 if (child.size && child.data == NULL)
2146 child.data = data = g_malloc0 (child.size);
2147 ok = check_tree (instance->children[i], child);
2148 g_variant_type_info_unref (child.type_info);
2149 g_free (data);
2151 if (!ok)
2152 return FALSE;
2155 return TRUE;
2157 else
2158 /* it is a leaf */
2160 switch (instance->data_size)
2162 case 1:
2163 g_assert (serialised.size == 1);
2164 return *(guint8 *) serialised.data ==
2165 (guint8) instance->data.integer;
2167 case 2:
2168 g_assert (serialised.size == 2);
2169 return *(guint16 *) serialised.data ==
2170 (guint16) instance->data.integer;
2172 case 4:
2173 g_assert (serialised.size == 4);
2174 return *(guint32 *) serialised.data ==
2175 (guint32) instance->data.integer;
2177 case 8:
2178 g_assert (serialised.size == 8);
2179 return *(guint64 *) serialised.data ==
2180 (guint64) instance->data.integer;
2182 default:
2183 if (serialised.size != instance->data_size)
2184 return FALSE;
2186 return memcmp (serialised.data,
2187 instance->data.string,
2188 instance->data_size) == 0;
2193 static void
2194 serialise_tree (TreeInstance *tree,
2195 GVariantSerialised *serialised)
2197 GVariantSerialised empty = { };
2199 *serialised = empty;
2200 tree_filler (serialised, tree);
2201 serialised->data = g_malloc (serialised->size);
2202 tree_filler (serialised, tree);
2205 static void
2206 test_byteswap (void)
2208 GVariantSerialised one, two;
2209 TreeInstance *tree;
2211 tree = tree_instance_new (NULL, 3);
2212 serialise_tree (tree, &one);
2214 i_am_writing_byteswapped = TRUE;
2215 serialise_tree (tree, &two);
2216 i_am_writing_byteswapped = FALSE;
2218 g_variant_serialised_byteswap (two);
2220 g_assert_cmpint (one.size, ==, two.size);
2221 g_assert (memcmp (one.data, two.data, one.size) == 0);
2223 tree_instance_free (tree);
2224 g_free (one.data);
2225 g_free (two.data);
2228 static void
2229 test_byteswaps (void)
2231 int i;
2233 for (i = 0; i < 200; i++)
2234 test_byteswap ();
2236 g_variant_type_info_assert_no_infos ();
2239 static void
2240 test_fuzz (gdouble *fuzziness)
2242 GVariantSerialised serialised;
2243 TreeInstance *tree;
2245 /* make an instance */
2246 tree = tree_instance_new (NULL, 3);
2248 /* serialise it */
2249 serialise_tree (tree, &serialised);
2251 g_assert (g_variant_serialised_is_normal (serialised));
2252 g_assert (check_tree (tree, serialised));
2254 if (serialised.size)
2256 gboolean fuzzed = FALSE;
2257 gboolean a, b;
2259 while (!fuzzed)
2261 gint i;
2263 for (i = 0; i < serialised.size; i++)
2264 if (randomly (*fuzziness))
2266 serialised.data[i] += g_test_rand_int_range (1, 256);
2267 fuzzed = TRUE;
2271 /* at least one byte in the serialised data has changed.
2273 * this means that at least one of the following is true:
2275 * - the serialised data now represents a different value:
2276 * check_tree() will return FALSE
2278 * - the serialised data is in non-normal form:
2279 * g_variant_serialiser_is_normal() will return FALSE
2281 * we always do both checks to increase exposure of the serialiser
2282 * to corrupt data.
2284 a = g_variant_serialised_is_normal (serialised);
2285 b = check_tree (tree, serialised);
2287 g_assert (!a || !b);
2290 tree_instance_free (tree);
2291 g_free (serialised.data);
2295 static void
2296 test_fuzzes (gpointer data)
2298 gdouble fuzziness;
2299 int i;
2301 fuzziness = GPOINTER_TO_INT (data) / 100.;
2303 for (i = 0; i < 200; i++)
2304 test_fuzz (&fuzziness);
2306 g_variant_type_info_assert_no_infos ();
2309 static GVariant *
2310 tree_instance_get_gvariant (TreeInstance *tree)
2312 const GVariantType *type;
2313 GVariant *result;
2315 type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
2317 switch (g_variant_type_info_get_type_char (tree->info))
2319 case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
2321 const GVariantType *child_type;
2322 GVariant *child;
2324 if (tree->n_children)
2325 child = tree_instance_get_gvariant (tree->children[0]);
2326 else
2327 child = NULL;
2329 child_type = g_variant_type_element (type);
2331 if (child != NULL && randomly (0.5))
2332 child_type = NULL;
2334 result = g_variant_new_maybe (child_type, child);
2336 break;
2338 case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
2340 const GVariantType *child_type;
2341 GVariant **children;
2342 gint i;
2344 children = g_new (GVariant *, tree->n_children);
2345 for (i = 0; i < tree->n_children; i++)
2346 children[i] = tree_instance_get_gvariant (tree->children[i]);
2348 child_type = g_variant_type_element (type);
2350 if (i > 0 && randomly (0.5))
2351 child_type = NULL;
2353 result = g_variant_new_array (child_type, children, tree->n_children);
2354 g_free (children);
2356 break;
2358 case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
2360 GVariant **children;
2361 gint i;
2363 children = g_new (GVariant *, tree->n_children);
2364 for (i = 0; i < tree->n_children; i++)
2365 children[i] = tree_instance_get_gvariant (tree->children[i]);
2367 result = g_variant_new_tuple (children, tree->n_children);
2368 g_free (children);
2370 break;
2372 case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
2374 GVariant *key, *val;
2376 g_assert (tree->n_children == 2);
2378 key = tree_instance_get_gvariant (tree->children[0]);
2379 val = tree_instance_get_gvariant (tree->children[1]);
2381 result = g_variant_new_dict_entry (key, val);
2383 break;
2385 case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
2387 GVariant *value;
2389 g_assert (tree->n_children == 1);
2391 value = tree_instance_get_gvariant (tree->children[0]);
2392 result = g_variant_new_variant (value);
2394 break;
2396 case 'b':
2397 result = g_variant_new_boolean (tree->data.integer > 0);
2398 break;
2400 case 'y':
2401 result = g_variant_new_byte (tree->data.integer);
2402 break;
2404 case 'n':
2405 result = g_variant_new_int16 (tree->data.integer);
2406 break;
2408 case 'q':
2409 result = g_variant_new_uint16 (tree->data.integer);
2410 break;
2412 case 'i':
2413 result = g_variant_new_int32 (tree->data.integer);
2414 break;
2416 case 'u':
2417 result = g_variant_new_uint32 (tree->data.integer);
2418 break;
2420 case 'x':
2421 result = g_variant_new_int64 (tree->data.integer);
2422 break;
2424 case 't':
2425 result = g_variant_new_uint64 (tree->data.integer);
2426 break;
2428 case 'h':
2429 result = g_variant_new_handle (tree->data.integer);
2430 break;
2432 case 'd':
2433 result = g_variant_new_double (tree->data.floating);
2434 break;
2436 case 's':
2437 result = g_variant_new_string (tree->data.string);
2438 break;
2440 case 'o':
2441 result = g_variant_new_object_path (tree->data.string);
2442 break;
2444 case 'g':
2445 result = g_variant_new_signature (tree->data.string);
2446 break;
2448 default:
2449 g_assert_not_reached ();
2452 return result;
2455 static gboolean
2456 tree_instance_check_gvariant (TreeInstance *tree,
2457 GVariant *value)
2459 const GVariantType *type;
2461 type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
2462 g_assert (g_variant_is_of_type (value, type));
2464 switch (g_variant_type_info_get_type_char (tree->info))
2466 case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
2468 GVariant *child;
2469 gboolean equal;
2471 child = g_variant_get_maybe (value);
2473 if (child != NULL && tree->n_children == 1)
2474 equal = tree_instance_check_gvariant (tree->children[0], child);
2475 else if (child == NULL && tree->n_children == 0)
2476 equal = TRUE;
2477 else
2478 equal = FALSE;
2480 if (child != NULL)
2481 g_variant_unref (child);
2483 return equal;
2485 break;
2487 case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
2488 case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
2489 case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
2491 gsize i;
2493 if (g_variant_n_children (value) != tree->n_children)
2494 return FALSE;
2496 for (i = 0; i < tree->n_children; i++)
2498 GVariant *child;
2499 gboolean equal;
2501 child = g_variant_get_child_value (value, i);
2502 equal = tree_instance_check_gvariant (tree->children[i], child);
2503 g_variant_unref (child);
2505 if (!equal)
2506 return FALSE;
2509 return TRUE;
2511 break;
2513 case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
2515 const gchar *str1, *str2;
2516 GVariant *child;
2517 gboolean equal;
2519 child = g_variant_get_variant (value);
2520 str1 = g_variant_get_type_string (child);
2521 str2 = g_variant_type_info_get_type_string (tree->children[0]->info);
2522 /* GVariant only keeps one copy of type strings around */
2523 equal = str1 == str2 &&
2524 tree_instance_check_gvariant (tree->children[0], child);
2526 g_variant_unref (child);
2528 return equal;
2530 break;
2532 case 'b':
2533 return g_variant_get_boolean (value) == tree->data.integer;
2535 case 'y':
2536 return g_variant_get_byte (value) == (guchar) tree->data.integer;
2538 case 'n':
2539 return g_variant_get_int16 (value) == (gint16) tree->data.integer;
2541 case 'q':
2542 return g_variant_get_uint16 (value) == (guint16) tree->data.integer;
2544 case 'i':
2545 return g_variant_get_int32 (value) == (gint32) tree->data.integer;
2547 case 'u':
2548 return g_variant_get_uint32 (value) == (guint32) tree->data.integer;
2550 case 'x':
2551 return g_variant_get_int64 (value) == (gint64) tree->data.integer;
2553 case 't':
2554 return g_variant_get_uint64 (value) == (guint64) tree->data.integer;
2556 case 'h':
2557 return g_variant_get_handle (value) == (gint32) tree->data.integer;
2559 case 'd':
2561 gdouble floating = g_variant_get_double (value);
2563 return memcmp (&floating, &tree->data.floating, sizeof floating) == 0;
2566 case 's':
2567 case 'o':
2568 case 'g':
2569 return strcmp (g_variant_get_string (value, NULL),
2570 tree->data.string) == 0;
2572 default:
2573 g_assert_not_reached ();
2577 static void
2578 tree_instance_build_gvariant (TreeInstance *tree,
2579 GVariantBuilder *builder,
2580 gboolean guess_ok)
2582 const GVariantType *type;
2584 type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
2586 if (g_variant_type_is_container (type))
2588 gsize i;
2590 /* force GVariantBuilder to guess the type half the time */
2591 if (guess_ok && randomly (0.5))
2593 if (g_variant_type_is_array (type) && tree->n_children)
2594 type = G_VARIANT_TYPE_ARRAY;
2596 if (g_variant_type_is_maybe (type) && tree->n_children)
2597 type = G_VARIANT_TYPE_MAYBE;
2599 if (g_variant_type_is_tuple (type))
2600 type = G_VARIANT_TYPE_TUPLE;
2602 if (g_variant_type_is_dict_entry (type))
2603 type = G_VARIANT_TYPE_DICT_ENTRY;
2605 else
2606 guess_ok = FALSE;
2608 g_variant_builder_open (builder, type);
2610 for (i = 0; i < tree->n_children; i++)
2611 tree_instance_build_gvariant (tree->children[i], builder, guess_ok);
2613 g_variant_builder_close (builder);
2615 else
2616 g_variant_builder_add_value (builder, tree_instance_get_gvariant (tree));
2620 static gboolean
2621 tree_instance_check_iter (TreeInstance *tree,
2622 GVariantIter *iter)
2624 GVariant *value;
2626 value = g_variant_iter_next_value (iter);
2628 if (g_variant_is_container (value))
2630 gsize i;
2632 iter = g_variant_iter_new (value);
2633 g_variant_unref (value);
2635 if (g_variant_iter_n_children (iter) != tree->n_children)
2637 g_variant_iter_free (iter);
2638 return FALSE;
2641 for (i = 0; i < tree->n_children; i++)
2642 if (!tree_instance_check_iter (tree->children[i], iter))
2644 g_variant_iter_free (iter);
2645 return FALSE;
2648 g_assert (g_variant_iter_next_value (iter) == NULL);
2649 g_variant_iter_free (iter);
2651 return TRUE;
2654 else
2656 gboolean equal;
2658 equal = tree_instance_check_gvariant (tree, value);
2659 g_variant_unref (value);
2661 return equal;
2665 static void
2666 test_container (void)
2668 TreeInstance *tree;
2669 GVariant *value;
2670 gchar *s1, *s2;
2672 tree = tree_instance_new (NULL, 3);
2673 value = g_variant_ref_sink (tree_instance_get_gvariant (tree));
2675 s1 = g_variant_print (value, TRUE);
2676 g_assert (tree_instance_check_gvariant (tree, value));
2678 g_variant_get_data (value);
2680 s2 = g_variant_print (value, TRUE);
2681 g_assert (tree_instance_check_gvariant (tree, value));
2683 g_assert_cmpstr (s1, ==, s2);
2685 if (g_variant_is_container (value))
2687 GVariantBuilder builder;
2688 GVariantIter iter;
2689 GVariant *built;
2690 GVariant *val;
2691 gchar *s3;
2693 g_variant_builder_init (&builder, G_VARIANT_TYPE_VARIANT);
2694 tree_instance_build_gvariant (tree, &builder, TRUE);
2695 built = g_variant_builder_end (&builder);
2696 g_variant_ref_sink (built);
2697 g_variant_get_data (built);
2698 val = g_variant_get_variant (built);
2700 s3 = g_variant_print (val, TRUE);
2701 g_assert_cmpstr (s1, ==, s3);
2703 g_variant_iter_init (&iter, built);
2704 g_assert (tree_instance_check_iter (tree, &iter));
2705 g_assert (g_variant_iter_next_value (&iter) == NULL);
2707 g_variant_unref (built);
2708 g_variant_unref (val);
2709 g_free (s3);
2712 tree_instance_free (tree);
2713 g_variant_unref (value);
2714 g_free (s2);
2715 g_free (s1);
2718 static void
2719 test_utf8 (void)
2721 const gchar invalid[] = "hello\xffworld";
2722 GVariant *value;
2724 /* ensure that the test data is not valid utf8... */
2725 g_assert (!g_utf8_validate (invalid, -1, NULL));
2727 /* load the data untrusted */
2728 value = g_variant_new_from_data (G_VARIANT_TYPE_STRING,
2729 invalid, sizeof invalid,
2730 FALSE, NULL, NULL);
2732 /* ensure that the problem is caught and we get valid UTF-8 */
2733 g_assert (g_utf8_validate (g_variant_get_string (value, NULL), -1, NULL));
2734 g_variant_unref (value);
2737 /* now load it trusted */
2738 value = g_variant_new_from_data (G_VARIANT_TYPE_STRING,
2739 invalid, sizeof invalid,
2740 TRUE, NULL, NULL);
2742 /* ensure we get the invalid data (ie: make sure that time wasn't
2743 * wasted on validating data that was marked as trusted)
2745 g_assert (g_variant_get_string (value, NULL) == invalid);
2746 g_variant_unref (value);
2749 static void
2750 test_containers (void)
2752 gint i;
2754 for (i = 0; i < 100; i++)
2756 test_container ();
2759 g_variant_type_info_assert_no_infos ();
2762 static void
2763 test_format_strings (void)
2765 GVariantType *type;
2766 const gchar *end;
2768 g_assert (g_variant_format_string_scan ("i", NULL, &end) && *end == '\0');
2769 g_assert (g_variant_format_string_scan ("@i", NULL, &end) && *end == '\0');
2770 g_assert (g_variant_format_string_scan ("@ii", NULL, &end) && *end == 'i');
2771 g_assert (g_variant_format_string_scan ("^a&s", NULL, &end) && *end == '\0');
2772 g_assert (g_variant_format_string_scan ("(^as)", NULL, &end) &&
2773 *end == '\0');
2774 g_assert (!g_variant_format_string_scan ("(^s)", NULL, &end));
2775 g_assert (!g_variant_format_string_scan ("(^a)", NULL, &end));
2776 g_assert (!g_variant_format_string_scan ("(z)", NULL, &end));
2777 g_assert (!g_variant_format_string_scan ("az", NULL, &end));
2778 g_assert (!g_variant_format_string_scan ("{**}", NULL, &end));
2779 g_assert (!g_variant_format_string_scan ("{@**}", NULL, &end));
2780 g_assert (g_variant_format_string_scan ("{@y*}", NULL, &end) &&
2781 *end == '\0');
2782 g_assert (g_variant_format_string_scan ("{yv}", NULL, &end) &&
2783 *end == '\0');
2784 g_assert (!g_variant_format_string_scan ("{&?v}", NULL, &end));
2785 g_assert (g_variant_format_string_scan ("{@?v}", NULL, &end) &&
2786 *end == '\0');
2787 g_assert (!g_variant_format_string_scan ("{&@sv}", NULL, &end));
2788 g_assert (!g_variant_format_string_scan ("{@&sv}", NULL, &end));
2789 g_assert (g_variant_format_string_scan ("{&sv}", NULL, &end) &&
2790 *end == '\0');
2791 g_assert (!g_variant_format_string_scan ("{vv}", NULL, &end));
2792 g_assert (!g_variant_format_string_scan ("{y}", NULL, &end));
2793 g_assert (!g_variant_format_string_scan ("{yyy}", NULL, &end));
2794 g_assert (!g_variant_format_string_scan ("{ya}", NULL, &end));
2795 g_assert (g_variant_format_string_scan ("&s", NULL, &end) && *end == '\0');
2796 g_assert (!g_variant_format_string_scan ("&as", NULL, &end));
2797 g_assert (!g_variant_format_string_scan ("@z", NULL, &end));
2798 g_assert (!g_variant_format_string_scan ("az", NULL, &end));
2799 g_assert (!g_variant_format_string_scan ("a&s", NULL, &end));
2801 type = g_variant_format_string_scan_type ("mm(@xy^a&s*?@?)", NULL, &end);
2802 g_assert (type && *end == '\0');
2803 g_assert (g_variant_type_equal (type, G_VARIANT_TYPE ("mm(xyas*?\?)")));
2804 g_variant_type_free (type);
2806 type = g_variant_format_string_scan_type ("mm(@xy^a&*?@?)", NULL, NULL);
2807 g_assert (type == NULL);
2810 static void
2811 exit_on_abort (int signal)
2813 exit (signal);
2816 static gboolean
2817 do_failed_test (const gchar *pattern)
2819 if (g_test_trap_fork (1000000, G_TEST_TRAP_SILENCE_STDERR))
2821 signal (SIGABRT, exit_on_abort);
2822 return TRUE;
2825 g_test_trap_assert_failed ();
2826 g_test_trap_assert_stderr (pattern);
2828 return FALSE;
2831 static void
2832 test_invalid_varargs (void)
2834 if (do_failed_test ("*GVariant format string*"))
2836 g_variant_new ("z");
2837 abort ();
2840 if (do_failed_test ("*valid GVariant format string as a prefix*"))
2842 const gchar *end;
2844 g_variant_new_va ("z", &end, NULL);
2845 abort ();
2848 if (do_failed_test ("*type of `q' but * has a type of `y'*"))
2850 g_variant_get (g_variant_new ("y", 'a'), "q");
2851 abort ();
2855 static void
2856 check_and_free (GVariant *value,
2857 const gchar *str)
2859 gchar *valstr = g_variant_print (value, FALSE);
2860 g_assert_cmpstr (str, ==, valstr);
2861 g_variant_unref (value);
2862 g_free (valstr);
2865 static void
2866 test_varargs (void)
2869 GVariantBuilder array;
2871 g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
2872 g_variant_builder_add_parsed (&array, "{'size', <(%i, %i)> }", 800, 600);
2873 g_variant_builder_add (&array, "{sv}", "title",
2874 g_variant_new_string ("Test case"));
2875 g_variant_builder_add_value (&array,
2876 g_variant_new_dict_entry (g_variant_new_string ("temperature"),
2877 g_variant_new_variant (
2878 g_variant_new_double (37.5))));
2879 check_and_free (g_variant_new ("(ma{sv}m(a{sv})ma{sv}ii)",
2880 NULL, FALSE, NULL, &array, 7777, 8888),
2881 "(nothing, nothing, {'size': <(800, 600)>, "
2882 "'title': <'Test case'>, "
2883 "'temperature': <37.5>}, "
2884 "7777, 8888)");
2886 check_and_free (g_variant_new ("(imimimmimmimmi)",
2887 123,
2888 FALSE, 321,
2889 TRUE, 123,
2890 FALSE, TRUE, 321,
2891 TRUE, FALSE, 321,
2892 TRUE, TRUE, 123),
2893 "(123, nothing, 123, nothing, just nothing, 123)");
2895 check_and_free (g_variant_new ("(ybnixd)",
2896 'a', 1, 22, 33, (guint64) 44, 5.5),
2897 "(0x61, true, 22, 33, 44, 5.5)");
2899 check_and_free (g_variant_new ("(@y?*rv)",
2900 g_variant_new ("y", 'a'),
2901 g_variant_new ("y", 'b'),
2902 g_variant_new ("y", 'c'),
2903 g_variant_new ("(y)", 'd'),
2904 g_variant_new ("y", 'e')),
2905 "(0x61, 0x62, 0x63, (0x64,), <byte 0x65>)");
2909 GVariantBuilder array;
2910 GVariantIter iter;
2911 GVariant *value;
2912 gchar *number;
2913 gboolean just;
2914 gint i, val;
2916 g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
2917 for (i = 0; i < 100; i++)
2919 number = g_strdup_printf ("%d", i);
2920 g_variant_builder_add (&array, "s", number);
2921 g_free (number);
2924 value = g_variant_builder_end (&array);
2925 g_variant_iter_init (&iter, value);
2927 i = 0;
2928 while (g_variant_iter_loop (&iter, "s", &number))
2930 gchar *check = g_strdup_printf ("%d", i++);
2931 g_assert_cmpstr (number, ==, check);
2932 g_free (check);
2934 g_assert (number == NULL);
2935 g_assert (i == 100);
2937 g_variant_unref (value);
2939 g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
2940 for (i = 0; i < 100; i++)
2941 g_variant_builder_add (&array, "mi", i % 2 == 0, i);
2942 value = g_variant_builder_end (&array);
2944 i = 0;
2945 g_variant_iter_init (&iter, value);
2946 while (g_variant_iter_loop (&iter, "mi", NULL, &val))
2947 g_assert (val == i++ || val == 0);
2948 g_assert (i == 100);
2950 i = 0;
2951 g_variant_iter_init (&iter, value);
2952 while (g_variant_iter_loop (&iter, "mi", &just, &val))
2954 gint this = i++;
2956 if (this % 2 == 0)
2958 g_assert (just);
2959 g_assert (val == this);
2961 else
2963 g_assert (!just);
2964 g_assert (val == 0);
2967 g_assert (i == 100);
2969 g_variant_unref (value);
2973 const gchar *strvector[] = {"/hello", "/world", NULL};
2974 const gchar *test_strs[] = {"/foo", "/bar", "/baz" };
2975 GVariantBuilder builder;
2976 GVariantIter *array;
2977 GVariantIter tuple;
2978 const gchar **strv;
2979 gchar **my_strv;
2980 GVariant *value;
2981 gchar *str;
2982 gint i;
2984 g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
2985 g_variant_builder_add (&builder, "s", "/foo");
2986 g_variant_builder_add (&builder, "s", "/bar");
2987 g_variant_builder_add (&builder, "s", "/baz");
2988 value = g_variant_new("(as^as^a&s)", &builder, strvector, strvector);
2989 g_variant_iter_init (&tuple, value);
2990 g_variant_iter_next (&tuple, "as", &array);
2992 i = 0;
2993 while (g_variant_iter_loop (array, "s", &str))
2994 g_assert_cmpstr (str, ==, test_strs[i++]);
2995 g_assert (i == 3);
2997 g_variant_iter_free (array);
2999 /* start over */
3000 g_variant_iter_init (&tuple, value);
3001 g_variant_iter_next (&tuple, "as", &array);
3003 i = 0;
3004 while (g_variant_iter_loop (array, "&s", &str))
3005 g_assert_cmpstr (str, ==, test_strs[i++]);
3006 g_assert (i == 3);
3008 g_variant_iter_free (array);
3010 g_variant_iter_next (&tuple, "^a&s", &strv);
3011 g_variant_iter_next (&tuple, "^as", &my_strv);
3013 g_assert_cmpstr (strv[0], ==, "/hello");
3014 g_assert_cmpstr (strv[1], ==, "/world");
3015 g_assert (strv[2] == NULL);
3016 g_assert_cmpstr (my_strv[0], ==, "/hello");
3017 g_assert_cmpstr (my_strv[1], ==, "/world");
3018 g_assert (my_strv[2] == NULL);
3020 g_variant_unref (value);
3021 g_strfreev (my_strv);
3022 g_free (strv);
3026 const gchar *strvector[] = { "i", "ii", "iii", "iv", "v", "vi", NULL };
3027 GVariantBuilder builder;
3028 GVariantIter iter;
3029 GVariantIter *i2;
3030 GVariantIter *i3;
3031 GVariant *value;
3032 GVariant *sub;
3033 gchar **strv;
3034 gint i;
3036 g_variant_builder_init (&builder, G_VARIANT_TYPE ("aas"));
3037 g_variant_builder_open (&builder, G_VARIANT_TYPE ("as"));
3038 for (i = 0; i < 6; i++)
3039 if (i & 1)
3040 g_variant_builder_add (&builder, "s", strvector[i]);
3041 else
3042 g_variant_builder_add (&builder, "&s", strvector[i]);
3043 g_variant_builder_close (&builder);
3044 g_variant_builder_add (&builder, "^as", strvector);
3045 g_variant_builder_add (&builder, "^as", strvector);
3046 value = g_variant_new ("aas", &builder);
3048 g_variant_iter_init (&iter, value);
3049 while (g_variant_iter_loop (&iter, "^as", &strv))
3050 for (i = 0; i < 6; i++)
3051 g_assert_cmpstr (strv[i], ==, strvector[i]);
3053 g_variant_iter_init (&iter, value);
3054 while (g_variant_iter_loop (&iter, "^a&s", &strv))
3055 for (i = 0; i < 6; i++)
3056 g_assert_cmpstr (strv[i], ==, strvector[i]);
3058 g_variant_iter_init (&iter, value);
3059 while (g_variant_iter_loop (&iter, "as", &i2))
3061 gchar *str;
3063 i = 0;
3064 while (g_variant_iter_loop (i2, "s", &str))
3065 g_assert_cmpstr (str, ==, strvector[i++]);
3066 g_assert (i == 6);
3069 g_variant_iter_init (&iter, value);
3070 i3 = g_variant_iter_copy (&iter);
3071 while (g_variant_iter_loop (&iter, "@as", &sub))
3073 gchar *str = g_variant_print (sub, TRUE);
3074 g_assert_cmpstr (str, ==,
3075 "['i', 'ii', 'iii', 'iv', 'v', 'vi']");
3076 g_free (str);
3079 if (do_failed_test ("*NULL has already been returned*"))
3081 g_variant_iter_next_value (&iter);
3082 abort ();
3086 while (g_variant_iter_loop (i3, "*", &sub))
3088 gchar *str = g_variant_print (sub, TRUE);
3089 g_assert_cmpstr (str, ==,
3090 "['i', 'ii', 'iii', 'iv', 'v', 'vi']");
3091 g_free (str);
3094 g_variant_iter_free (i3);
3096 for (i = 0; i < g_variant_n_children (value); i++)
3098 gint j;
3100 g_variant_get_child (value, i, "*", &sub);
3102 for (j = 0; j < g_variant_n_children (sub); j++)
3104 const gchar *str = NULL;
3105 GVariant *cval;
3107 g_variant_get_child (sub, j, "&s", &str);
3108 g_assert_cmpstr (str, ==, strvector[j]);
3110 cval = g_variant_get_child_value (sub, j);
3111 g_variant_get (cval, "&s", &str);
3112 g_assert_cmpstr (str, ==, strvector[j]);
3113 g_variant_unref (cval);
3116 g_variant_unref (sub);
3119 g_variant_unref (value);
3123 gboolean justs[10];
3124 GVariant *value;
3126 GVariant *vval;
3127 guchar byteval;
3128 gboolean bval;
3129 gint16 i16val;
3130 guint16 u16val;
3131 gint32 i32val;
3132 guint32 u32val;
3133 gint64 i64val;
3134 guint64 u64val;
3135 gdouble dval;
3136 gint32 hval;
3138 /* test all 'nothing' */
3139 value = g_variant_new ("(mymbmnmqmimumxmtmhmdmv)",
3140 FALSE, 'a',
3141 FALSE, TRUE,
3142 FALSE, (gint16) 123,
3143 FALSE, (guint16) 123,
3144 FALSE, (gint32) 123,
3145 FALSE, (guint32) 123,
3146 FALSE, (gint64) 123,
3147 FALSE, (guint64) 123,
3148 FALSE, (gint32) -1,
3149 FALSE, (gdouble) 37.5,
3150 NULL);
3152 /* both NULL */
3153 g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3154 NULL, NULL,
3155 NULL, NULL,
3156 NULL, NULL,
3157 NULL, NULL,
3158 NULL, NULL,
3159 NULL, NULL,
3160 NULL, NULL,
3161 NULL, NULL,
3162 NULL, NULL,
3163 NULL, NULL,
3164 NULL);
3166 /* NULL values */
3167 memset (justs, 1, sizeof justs);
3168 g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3169 &justs[0], NULL,
3170 &justs[1], NULL,
3171 &justs[2], NULL,
3172 &justs[3], NULL,
3173 &justs[4], NULL,
3174 &justs[5], NULL,
3175 &justs[6], NULL,
3176 &justs[7], NULL,
3177 &justs[8], NULL,
3178 &justs[9], NULL,
3179 NULL);
3180 g_assert (!(justs[0] || justs[1] || justs[2] || justs[3] || justs[4] ||
3181 justs[5] || justs[6] || justs[7] || justs[8] || justs[9]));
3183 /* both non-NULL */
3184 memset (justs, 1, sizeof justs);
3185 byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3186 vval = (void *) 1;
3187 bval = TRUE;
3188 dval = 88.88;
3189 g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3190 &justs[0], &byteval,
3191 &justs[1], &bval,
3192 &justs[2], &i16val,
3193 &justs[3], &u16val,
3194 &justs[4], &i32val,
3195 &justs[5], &u32val,
3196 &justs[6], &i64val,
3197 &justs[7], &u64val,
3198 &justs[8], &hval,
3199 &justs[9], &dval,
3200 &vval);
3201 g_assert (!(justs[0] || justs[1] || justs[2] || justs[3] || justs[4] ||
3202 justs[5] || justs[6] || justs[7] || justs[8] || justs[9]));
3203 g_assert (byteval == '\0' && bval == FALSE);
3204 g_assert (i16val == 0 && u16val == 0 && i32val == 0 &&
3205 u32val == 0 && i64val == 0 && u64val == 0 &&
3206 hval == 0 && dval == 0.0);
3207 g_assert (vval == NULL);
3209 /* NULL justs */
3210 byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3211 vval = (void *) 1;
3212 bval = TRUE;
3213 dval = 88.88;
3214 g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3215 NULL, &byteval,
3216 NULL, &bval,
3217 NULL, &i16val,
3218 NULL, &u16val,
3219 NULL, &i32val,
3220 NULL, &u32val,
3221 NULL, &i64val,
3222 NULL, &u64val,
3223 NULL, &hval,
3224 NULL, &dval,
3225 &vval);
3226 g_assert (byteval == '\0' && bval == FALSE);
3227 g_assert (i16val == 0 && u16val == 0 && i32val == 0 &&
3228 u32val == 0 && i64val == 0 && u64val == 0 &&
3229 hval == 0 && dval == 0.0);
3230 g_assert (vval == NULL);
3232 g_variant_unref (value);
3235 /* test all 'just' */
3236 value = g_variant_new ("(mymbmnmqmimumxmtmhmdmv)",
3237 TRUE, 'a',
3238 TRUE, TRUE,
3239 TRUE, (gint16) 123,
3240 TRUE, (guint16) 123,
3241 TRUE, (gint32) 123,
3242 TRUE, (guint32) 123,
3243 TRUE, (gint64) 123,
3244 TRUE, (guint64) 123,
3245 TRUE, (gint32) -1,
3246 TRUE, (gdouble) 37.5,
3247 g_variant_new ("()"));
3249 /* both NULL */
3250 g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3251 NULL, NULL,
3252 NULL, NULL,
3253 NULL, NULL,
3254 NULL, NULL,
3255 NULL, NULL,
3256 NULL, NULL,
3257 NULL, NULL,
3258 NULL, NULL,
3259 NULL, NULL,
3260 NULL, NULL,
3261 NULL);
3263 /* NULL values */
3264 memset (justs, 0, sizeof justs);
3265 g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3266 &justs[0], NULL,
3267 &justs[1], NULL,
3268 &justs[2], NULL,
3269 &justs[3], NULL,
3270 &justs[4], NULL,
3271 &justs[5], NULL,
3272 &justs[6], NULL,
3273 &justs[7], NULL,
3274 &justs[8], NULL,
3275 &justs[9], NULL,
3276 NULL);
3277 g_assert (justs[0] && justs[1] && justs[2] && justs[3] && justs[4] &&
3278 justs[5] && justs[6] && justs[7] && justs[8] && justs[9]);
3280 /* both non-NULL */
3281 memset (justs, 0, sizeof justs);
3282 byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3283 vval = (void *) 1;
3284 bval = FALSE;
3285 dval = 88.88;
3286 g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3287 &justs[0], &byteval,
3288 &justs[1], &bval,
3289 &justs[2], &i16val,
3290 &justs[3], &u16val,
3291 &justs[4], &i32val,
3292 &justs[5], &u32val,
3293 &justs[6], &i64val,
3294 &justs[7], &u64val,
3295 &justs[8], &hval,
3296 &justs[9], &dval,
3297 &vval);
3298 g_assert (justs[0] && justs[1] && justs[2] && justs[3] && justs[4] &&
3299 justs[5] && justs[6] && justs[7] && justs[8] && justs[9]);
3300 g_assert (byteval == 'a' && bval == TRUE);
3301 g_assert (i16val == 123 && u16val == 123 && i32val == 123 &&
3302 u32val == 123 && i64val == 123 && u64val == 123 &&
3303 hval == -1 && dval == 37.5);
3304 g_assert (g_variant_is_of_type (vval, G_VARIANT_TYPE_UNIT));
3305 g_variant_unref (vval);
3307 /* NULL justs */
3308 byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3309 vval = (void *) 1;
3310 bval = TRUE;
3311 dval = 88.88;
3312 g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3313 NULL, &byteval,
3314 NULL, &bval,
3315 NULL, &i16val,
3316 NULL, &u16val,
3317 NULL, &i32val,
3318 NULL, &u32val,
3319 NULL, &i64val,
3320 NULL, &u64val,
3321 NULL, &hval,
3322 NULL, &dval,
3323 &vval);
3324 g_assert (byteval == 'a' && bval == TRUE);
3325 g_assert (i16val == 123 && u16val == 123 && i32val == 123 &&
3326 u32val == 123 && i64val == 123 && u64val == 123 &&
3327 hval == -1 && dval == 37.5);
3328 g_assert (g_variant_is_of_type (vval, G_VARIANT_TYPE_UNIT));
3329 g_variant_unref (vval);
3331 g_variant_unref (value);
3334 g_variant_type_info_assert_no_infos ();
3337 static void
3338 hash_get (GVariant *value,
3339 const gchar *format,
3340 ...)
3342 const gchar *endptr = NULL;
3343 gboolean hash;
3344 va_list ap;
3346 hash = g_str_has_suffix (format, "#");
3348 va_start (ap, format);
3349 g_variant_get_va (value, format, hash ? &endptr : NULL, &ap);
3350 va_end (ap);
3352 if (hash)
3353 g_assert (*endptr == '#');
3356 static GVariant *
3357 hash_new (const gchar *format,
3358 ...)
3360 const gchar *endptr = NULL;
3361 GVariant *value;
3362 gboolean hash;
3363 va_list ap;
3365 hash = g_str_has_suffix (format, "#");
3367 va_start (ap, format);
3368 value = g_variant_new_va (format, hash ? &endptr : NULL, &ap);
3369 va_end (ap);
3371 if (hash)
3372 g_assert (*endptr == '#');
3374 return value;
3377 static void
3378 test_valist (void)
3380 GVariant *value;
3381 gint32 x;
3383 x = 0;
3384 value = hash_new ("i", 234);
3385 hash_get (value, "i", &x);
3386 g_assert (x == 234);
3387 g_variant_unref (value);
3389 x = 0;
3390 value = hash_new ("i#", 234);
3391 hash_get (value, "i#", &x);
3392 g_assert (x == 234);
3393 g_variant_unref (value);
3395 g_variant_type_info_assert_no_infos ();
3398 static void
3399 test_builder_memory (void)
3401 GVariantBuilder *hb;
3402 GVariantBuilder sb;
3404 hb = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
3405 g_variant_builder_open (hb, G_VARIANT_TYPE_ARRAY);
3406 g_variant_builder_open (hb, G_VARIANT_TYPE_ARRAY);
3407 g_variant_builder_open (hb, G_VARIANT_TYPE_ARRAY);
3408 g_variant_builder_add (hb, "s", "some value");
3409 g_variant_builder_ref (hb);
3410 g_variant_builder_unref (hb);
3411 g_variant_builder_unref (hb);
3413 hb = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
3414 g_variant_builder_unref (hb);
3416 hb = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
3417 g_variant_builder_clear (hb);
3418 g_variant_builder_unref (hb);
3420 g_variant_builder_init (&sb, G_VARIANT_TYPE_ARRAY);
3421 g_variant_builder_open (&sb, G_VARIANT_TYPE_ARRAY);
3422 g_variant_builder_open (&sb, G_VARIANT_TYPE_ARRAY);
3423 g_variant_builder_add (&sb, "s", "some value");
3424 g_variant_builder_clear (&sb);
3426 g_variant_type_info_assert_no_infos ();
3429 static void
3430 test_hashing (void)
3432 GVariant *items[4096];
3433 GHashTable *table;
3434 gint i;
3436 table = g_hash_table_new_full (g_variant_hash, g_variant_equal,
3437 (GDestroyNotify ) g_variant_unref,
3438 NULL);
3440 for (i = 0; i < G_N_ELEMENTS (items); i++)
3442 TreeInstance *tree;
3443 gint j;
3445 again:
3446 tree = tree_instance_new (NULL, 0);
3447 items[i] = tree_instance_get_gvariant (tree);
3448 tree_instance_free (tree);
3450 for (j = 0; j < i; j++)
3451 if (g_variant_equal (items[i], items[j]))
3453 g_variant_unref (items[i]);
3454 goto again;
3457 g_hash_table_insert (table,
3458 g_variant_ref_sink (items[i]),
3459 GINT_TO_POINTER (i));
3462 for (i = 0; i < G_N_ELEMENTS (items); i++)
3464 gpointer result;
3466 result = g_hash_table_lookup (table, items[i]);
3467 g_assert_cmpint (GPOINTER_TO_INT (result), ==, i);
3470 g_hash_table_unref (table);
3472 g_variant_type_info_assert_no_infos ();
3475 static void
3476 test_gv_byteswap ()
3478 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
3479 # define native16(x) x, 0
3480 # define swapped16(x) 0, x
3481 #else
3482 # define native16(x) 0, x
3483 # define swapped16(x) x, 0
3484 #endif
3485 /* all kinds of of crazy randomised testing already performed on the
3486 * byteswapper in the /gvariant/serialiser/byteswap test and all kinds
3487 * of crazy randomised testing performed against the serialiser
3488 * normalisation functions in the /gvariant/serialiser/fuzz/ tests.
3490 * just test a few simple cases here to make sure they each work
3492 guchar valid_data[] = { 'a', '\0', swapped16(66), 2,
3494 'b', '\0', swapped16(77), 2,
3495 5, 11 };
3496 guchar corrupt_data[] = { 'a', '\0', swapped16(66), 2,
3498 'b', '\0', swapped16(77), 2,
3499 6, 11 };
3500 GVariant *value, *swapped;
3501 gchar *string, *string2;
3504 /* trusted */
3505 value = g_variant_new_from_data (G_VARIANT_TYPE ("a(sn)"),
3506 valid_data, sizeof valid_data, TRUE,
3507 NULL, NULL);
3508 swapped = g_variant_byteswap (value);
3509 g_variant_unref (value);
3510 g_assert (g_variant_get_size (swapped) == 13);
3511 string = g_variant_print (swapped, FALSE);
3512 g_variant_unref (swapped);
3513 g_assert_cmpstr (string, ==, "[('a', 66), ('b', 77)]");
3514 g_free (string);
3516 /* untrusted but valid */
3517 value = g_variant_new_from_data (G_VARIANT_TYPE ("a(sn)"),
3518 valid_data, sizeof valid_data, FALSE,
3519 NULL, NULL);
3520 swapped = g_variant_byteswap (value);
3521 g_variant_unref (value);
3522 g_assert (g_variant_get_size (swapped) == 13);
3523 string = g_variant_print (swapped, FALSE);
3524 g_variant_unref (swapped);
3525 g_assert_cmpstr (string, ==, "[('a', 66), ('b', 77)]");
3526 g_free (string);
3528 /* untrusted, invalid */
3529 value = g_variant_new_from_data (G_VARIANT_TYPE ("a(sn)"),
3530 corrupt_data, sizeof corrupt_data, FALSE,
3531 NULL, NULL);
3532 string = g_variant_print (value, FALSE);
3533 swapped = g_variant_byteswap (value);
3534 g_variant_unref (value);
3535 g_assert (g_variant_get_size (swapped) == 13);
3536 value = g_variant_byteswap (swapped);
3537 g_variant_unref (swapped);
3538 string2 = g_variant_print (value, FALSE);
3539 g_assert (g_variant_get_size (value) == 13);
3540 g_variant_unref (value);
3541 g_assert_cmpstr (string, ==, string2);
3542 g_free (string2);
3543 g_free (string);
3546 static void
3547 test_parser (void)
3549 TreeInstance *tree;
3550 GVariant *parsed;
3551 GVariant *value;
3552 gchar *pt, *p;
3553 gchar *res;
3555 tree = tree_instance_new (NULL, 3);
3556 value = tree_instance_get_gvariant (tree);
3557 tree_instance_free (tree);
3559 pt = g_variant_print (value, TRUE);
3560 p = g_variant_print (value, FALSE);
3562 parsed = g_variant_parse (NULL, pt, NULL, NULL, NULL);
3563 res = g_variant_print (parsed, FALSE);
3564 g_assert_cmpstr (p, ==, res);
3565 g_variant_unref (parsed);
3566 g_free (res);
3568 parsed = g_variant_parse (g_variant_get_type (value), p,
3569 NULL, NULL, NULL);
3570 res = g_variant_print (parsed, TRUE);
3571 g_assert_cmpstr (pt, ==, res);
3572 g_variant_unref (parsed);
3573 g_free (res);
3575 g_variant_unref (value);
3576 g_free (pt);
3577 g_free (p);
3580 static void
3581 test_parses (void)
3583 gint i;
3585 for (i = 0; i < 100; i++)
3587 test_parser ();
3590 /* mini test */
3592 GError *error = NULL;
3593 gchar str[128];
3594 GVariant *val;
3595 gchar *p, *p2;
3597 for (i = 0; i < 127; i++)
3598 str[i] = i + 1;
3599 str[i] = 0;
3601 val = g_variant_new_string (str);
3602 p = g_variant_print (val, FALSE);
3603 g_variant_unref (val);
3605 val = g_variant_parse (NULL, p, NULL, NULL, &error);
3606 p2 = g_variant_print (val, FALSE);
3608 g_assert_cmpstr (str, ==, g_variant_get_string (val, NULL));
3609 g_assert_cmpstr (p, ==, p2);
3611 g_variant_unref (val);
3612 g_free (p2);
3613 g_free (p);
3616 /* another mini test */
3618 const gchar *end;
3619 GVariant *value;
3621 value = g_variant_parse (G_VARIANT_TYPE_INT32, "1 2 3", NULL, &end, NULL);
3622 g_assert_cmpint (g_variant_get_int32 (value), ==, 1);
3623 /* make sure endptr returning works */
3624 g_assert_cmpstr (end, ==, " 2 3");
3625 g_variant_unref (value);
3628 /* unicode mini test */
3630 /* ał𝄞 */
3631 const gchar orig[] = "a\xc5\x82\xf0\x9d\x84\x9e \t\n";
3632 GVariant *value;
3633 gchar *printed;
3635 value = g_variant_new_string (orig);
3636 printed = g_variant_print (value, FALSE);
3637 g_variant_unref (value);
3639 g_assert_cmpstr (printed, ==, "'a\xc5\x82\xf0\x9d\x84\x9e \\t\\n'");
3640 value = g_variant_parse (NULL, printed, NULL, NULL, NULL);
3641 g_assert_cmpstr (g_variant_get_string (value, NULL), ==, orig);
3642 g_variant_unref (value);
3643 g_free (printed);
3646 g_variant_type_info_assert_no_infos ();
3649 static void
3650 test_parse_failures (void)
3652 const gchar *test[] = {
3653 "[1, 2,", "6:", "expected value",
3654 "", "0:", "expected value",
3655 "(1, 2,", "6:", "expected value",
3656 "<1", "2:", "expected `>'",
3657 "[]", "0-2:", "unable to infer",
3658 "(,", "1:", "expected value",
3659 "[4,'']", "1-2,3-5:", "common type",
3660 "[4, '', 5]", "1-2,4-6:", "common type",
3661 "['', 4, 5]", "1-3,5-6:", "common type",
3662 "[4, 5, '']", "1-2,7-9:", "common type",
3663 "[[4], [], ['']]", "1-4,10-14:", "common type",
3664 "[[], [4], ['']]", "5-8,10-14:", "common type",
3665 "just", "4:", "expected value",
3666 "nothing", "0-7:", "unable to infer",
3667 "just [4, '']", "6-7,9-11:", "common type",
3668 "[[4,'']]", "2-3,4-6:", "common type",
3669 "([4,''],)", "2-3,4-6:", "common type",
3670 "(4)", "2:", "`,'",
3671 "{}", "0-2:", "unable to infer",
3672 "{[1,2],[3,4]}", "0-13:", "basic types",
3673 "{[1,2]:[3,4]}", "0-13:", "basic types",
3674 "justt", "0-5:", "unknown keyword",
3675 "nothng", "0-6:", "unknown keyword",
3676 "uint33", "0-6:", "unknown keyword",
3677 "@mi just ''", "9-11:", "can not parse as",
3678 "@ai ['']", "5-7:", "can not parse as",
3679 "@(i) ('',)", "6-8:", "can not parse as",
3680 "[[], 5]", "1-3,5-6:", "common type",
3681 "[[5], 5]", "1-4,6-7:", "common type",
3682 "5 5", "2:", "expected end of input",
3683 "[5, [5, '']]", "5-6,8-10:", "common type",
3684 "@i just 5", "3-9:", "can not parse as",
3685 "@i nothing", "3-10:", "can not parse as",
3686 "@i []", "3-5:", "can not parse as",
3687 "@i ()", "3-5:", "can not parse as",
3688 "@ai (4,)", "4-8:", "can not parse as",
3689 "@(i) []", "5-7:", "can not parse as",
3690 "(5 5)", "3:", "expected `,'",
3691 "[5 5]", "3:", "expected `,' or `]'",
3692 "(5, 5 5)", "6:", "expected `,' or `)'",
3693 "[5, 5 5]", "6:", "expected `,' or `]'",
3694 "<@i []>", "4-6:", "can not parse as",
3695 "<[5 5]>", "4:", "expected `,' or `]'",
3696 "{[4,''],5}", "2-3,4-6:", "common type",
3697 "{5,[4,'']}", "4-5,6-8:", "common type",
3698 "@i {1,2}", "3-8:", "can not parse as",
3699 "{@i '', 5}", "4-6:", "can not parse as",
3700 "{5, @i ''}", "7-9:", "can not parse as",
3701 "@ai {}", "4-6:", "can not parse as",
3702 "{@i '': 5}", "4-6:", "can not parse as",
3703 "{5: @i ''}", "7-9:", "can not parse as",
3704 "{<4,5}", "3:", "expected `>'",
3705 "{4,<5}", "5:", "expected `>'",
3706 "{4,5,6}", "4:", "expected `}'",
3707 "{5 5}", "3:", "expected `:' or `,'",
3708 "{4: 5: 6}", "5:", "expected `,' or `}'",
3709 "{4:5,<6:7}", "7:", "expected `>'",
3710 "{4:5,6:<7}", "9:", "expected `>'",
3711 "{4:5,6 7}", "7:", "expected `:'",
3712 "@o 'foo'", "3-8:", "object path",
3713 "@g 'zzz'", "3-8:", "signature",
3714 "@i true", "3-7:", "can not parse as",
3715 "@z 4", "0-2:", "invalid type",
3716 "@a* []", "0-3:", "definite",
3717 "@ai [3 3]", "7:", "expected `,' or `]'",
3718 "18446744073709551616", "0-20:", "too big for any type",
3719 "-18446744073709551616", "0-21:", "too big for any type",
3720 "byte 256", "5-8:", "out of range for type",
3721 "byte -1", "5-7:", "out of range for type",
3722 "int16 32768", "6-11:", "out of range for type",
3723 "int16 -32769", "6-12:", "out of range for type",
3724 "uint16 -1", "7-9:", "out of range for type",
3725 "uint16 65536", "7-12:", "out of range for type",
3726 "2147483648", "0-10:", "out of range for type",
3727 "-2147483649", "0-11:", "out of range for type",
3728 "uint32 -1", "7-9:", "out of range for type",
3729 "uint32 4294967296", "7-17:", "out of range for type",
3730 "@x 9223372036854775808", "3-22:", "out of range for type",
3731 "@x -9223372036854775809", "3-23:", "out of range for type",
3732 "@t -1", "3-5:", "out of range for type",
3733 "@t 18446744073709551616", "3-23:", "too big for any type",
3734 "handle 2147483648", "7-17:", "out of range for type",
3735 "handle -2147483649", "7-18:", "out of range for type",
3736 "1.798e308", "0-9:", "too big for any type",
3737 "37.5a488", "4-5:", "invalid character",
3738 "0x7ffgf", "5-6:", "invalid character",
3739 "07758", "4-5:", "invalid character",
3740 "123a5", "3-4:", "invalid character",
3741 "@ai 123", "4-7:", "can not parse as",
3742 "'\"\\'", "0-4:", "unterminated string",
3743 "'\"\\'\\", "0-5:", "unterminated string",
3744 "boolean 4", "8-9:", "can not parse as",
3745 "int32 true", "6-10:", "can not parse as",
3746 "[double 5, int32 5]", "1-9,11-18:", "common type",
3747 "string 4", "7-8:", "can not parse as"
3749 gint i;
3751 for (i = 0; i < G_N_ELEMENTS (test); i += 3)
3753 GError *error = NULL;
3754 GVariant *value;
3756 value = g_variant_parse (NULL, test[i], NULL, NULL, &error);
3757 g_assert (value == NULL);
3759 if (!strstr (error->message, test[i+2]))
3760 g_error ("test %d: Can't find `%s' in `%s'", i / 3,
3761 test[i+2], error->message);
3763 if (!g_str_has_prefix (error->message, test[i+1]))
3764 g_error ("test %d: Expected location `%s' in `%s'", i / 3,
3765 test[i+1], error->message);
3767 g_error_free (error);
3771 static void
3772 test_parse_positional (void)
3774 GVariant *value;
3775 check_and_free (g_variant_new_parsed ("[('one', 1), (%s, 2),"
3776 " ('three', %i)]", "two", 3),
3777 "[('one', 1), ('two', 2), ('three', 3)]");
3778 value = g_variant_new_parsed ("[('one', 1), (%s, 2),"
3779 " ('three', %u)]", "two", 3);
3780 g_assert (g_variant_is_of_type (value, G_VARIANT_TYPE ("a(su)")));
3781 check_and_free (value, "[('one', 1), ('two', 2), ('three', 3)]");
3782 check_and_free (g_variant_new_parsed ("{%s:%i}", "one", 1), "{'one': 1}");
3784 if (do_failed_test ("*GVariant format string*"))
3786 g_variant_new_parsed ("%z");
3787 abort ();
3790 if (do_failed_test ("*can not parse as*"))
3792 g_variant_new_parsed ("uint32 %i", 2);
3793 abort ();
3796 if (do_failed_test ("*expected GVariant of type `i'*"))
3798 g_variant_new_parsed ("%@i", g_variant_new_uint32 (2));
3799 abort ();
3803 static void
3804 test_floating (void)
3806 GVariant *value;
3808 value = g_variant_new_int32 (42);
3809 g_assert (g_variant_is_floating (value));
3810 g_variant_ref_sink (value);
3811 g_assert (!g_variant_is_floating (value));
3812 g_variant_unref (value);
3815 static void
3816 test_bytestring (void)
3818 const gchar *test_string = "foo,bar,baz,quux,\xffoooo";
3819 GVariant *value;
3820 gchar **strv;
3821 gchar *str;
3823 strv = g_strsplit (test_string, ",", 0);
3825 value = g_variant_new_bytestring_array ((const gchar **) strv, -1);
3826 g_assert (g_variant_is_floating (value));
3827 g_strfreev (strv);
3829 str = g_variant_print (value, FALSE);
3830 g_variant_unref (value);
3832 value = g_variant_parse (NULL, str, NULL, NULL, NULL);
3833 g_free (str);
3835 strv = g_variant_dup_bytestring_array (value, NULL);
3836 g_variant_unref (value);
3838 str = g_strjoinv (",", strv);
3839 g_strfreev (strv);
3841 g_assert_cmpstr (str, ==, test_string);
3842 g_free (str);
3844 strv = g_strsplit (test_string, ",", 0);
3845 value = g_variant_new ("(^aay^a&ay^ay^&ay)",
3846 strv, strv, strv[0], strv[0]);
3847 g_strfreev (strv);
3849 g_variant_get_child (value, 0, "^a&ay", &strv);
3850 str = g_strjoinv (",", strv);
3851 g_free (strv);
3852 g_assert_cmpstr (str, ==, test_string);
3853 g_free (str);
3855 g_variant_get_child (value, 0, "^aay", &strv);
3856 str = g_strjoinv (",", strv);
3857 g_strfreev (strv);
3858 g_assert_cmpstr (str, ==, test_string);
3859 g_free (str);
3861 g_variant_get_child (value, 1, "^a&ay", &strv);
3862 str = g_strjoinv (",", strv);
3863 g_free (strv);
3864 g_assert_cmpstr (str, ==, test_string);
3865 g_free (str);
3867 g_variant_get_child (value, 1, "^aay", &strv);
3868 str = g_strjoinv (",", strv);
3869 g_strfreev (strv);
3870 g_assert_cmpstr (str, ==, test_string);
3871 g_free (str);
3873 g_variant_get_child (value, 2, "^ay", &str);
3874 g_assert_cmpstr (str, ==, "foo");
3875 g_free (str);
3877 g_variant_get_child (value, 2, "^&ay", &str);
3878 g_assert_cmpstr (str, ==, "foo");
3880 g_variant_get_child (value, 3, "^ay", &str);
3881 g_assert_cmpstr (str, ==, "foo");
3882 g_free (str);
3884 g_variant_get_child (value, 3, "^&ay", &str);
3885 g_assert_cmpstr (str, ==, "foo");
3886 g_variant_unref (value);
3890 main (int argc, char **argv)
3892 gint i;
3894 g_test_init (&argc, &argv, NULL);
3896 g_test_add_func ("/gvariant/type", test_gvarianttype);
3897 g_test_add_func ("/gvariant/typeinfo", test_gvarianttypeinfo);
3898 g_test_add_func ("/gvariant/serialiser/maybe", test_maybes);
3899 g_test_add_func ("/gvariant/serialiser/array", test_arrays);
3900 g_test_add_func ("/gvariant/serialiser/tuple", test_tuples);
3901 g_test_add_func ("/gvariant/serialiser/variant", test_variants);
3902 g_test_add_func ("/gvariant/serialiser/strings", test_strings);
3903 g_test_add_func ("/gvariant/serialiser/byteswap", test_byteswaps);
3905 for (i = 1; i <= 20; i += 4)
3907 char *testname;
3909 testname = g_strdup_printf ("/gvariant/serialiser/fuzz/%d%%", i);
3910 g_test_add_data_func (testname, GINT_TO_POINTER (i),
3911 (gpointer) test_fuzzes);
3912 g_free (testname);
3915 g_test_add_func ("/gvariant/utf8", test_utf8);
3916 g_test_add_func ("/gvariant/containers", test_containers);
3917 g_test_add_func ("/gvariant/format-strings", test_format_strings);
3918 g_test_add_func ("/gvariant/invalid-varargs", test_invalid_varargs);
3919 g_test_add_func ("/gvariant/varargs", test_varargs);
3920 g_test_add_func ("/gvariant/valist", test_valist);
3921 g_test_add_func ("/gvariant/builder-memory", test_builder_memory);
3922 g_test_add_func ("/gvariant/hashing", test_hashing);
3923 g_test_add_func ("/gvariant/byteswap", test_gv_byteswap);
3924 g_test_add_func ("/gvariant/parser", test_parses);
3925 g_test_add_func ("/gvariant/parse-failures", test_parse_failures);
3926 g_test_add_func ("/gvariant/parse-positional", test_parse_positional);
3927 g_test_add_func ("/gvariant/floating", test_floating);
3928 g_test_add_func ("/gvariant/bytestring", test_bytestring);
3930 return g_test_run ();