2 * Copyright © 2010 Codethink Limited
3 * Copyright © 2020 William Manley
4 * Copyright © 2022 Endless OS Foundation, LLC
6 * SPDX-License-Identifier: LGPL-2.1-or-later
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * See the included COPYING file for more information.
15 * Author: Ryan Lortie <desrt@desrt.ca>
20 #include <glib/gvariant-internal.h>
25 #define BASIC "bynqiuxthdsog?"
26 #define N_BASIC (G_N_ELEMENTS (BASIC) - 1)
28 #define INVALIDS "cefjklpwz&@^$"
29 #define N_INVALIDS (G_N_ELEMENTS (INVALIDS) - 1)
31 /* see comment in gvariant-serialiser.c about this madness.
33 * we use this to get testing of non-strictly-aligned GVariant instances
34 * on machines that can tolerate it. it is necessary to support this
35 * because some systems have malloc() that returns non-8-aligned
36 * pointers. it is necessary to have special support in the tests
37 * because on most machines malloc() is 8-aligned.
39 #define ALIGN_BITS (sizeof (struct { char a; union { \
40 guint64 x; void *y; gdouble z; } b; }) - 9)
43 randomly (gdouble prob)
45 return g_test_rand_double_range (0, 1) < prob;
50 append_tuple_type_string (GString *, GString *, gboolean, gint);
52 /* append a random GVariantType to a GString
53 * append a description of the type to another GString
54 * return what the type is
57 append_type_string (GString *string,
62 if (!depth-- || randomly (0.3))
64 gchar b = BASIC[g_test_rand_int_range (0, N_BASIC - definite)];
65 g_string_append_c (string, b);
66 g_string_append_c (description, b);
71 return g_variant_type_copy (G_VARIANT_TYPE_BOOLEAN);
73 return g_variant_type_copy (G_VARIANT_TYPE_BYTE);
75 return g_variant_type_copy (G_VARIANT_TYPE_INT16);
77 return g_variant_type_copy (G_VARIANT_TYPE_UINT16);
79 return g_variant_type_copy (G_VARIANT_TYPE_INT32);
81 return g_variant_type_copy (G_VARIANT_TYPE_UINT32);
83 return g_variant_type_copy (G_VARIANT_TYPE_INT64);
85 return g_variant_type_copy (G_VARIANT_TYPE_UINT64);
87 return g_variant_type_copy (G_VARIANT_TYPE_HANDLE);
89 return g_variant_type_copy (G_VARIANT_TYPE_DOUBLE);
91 return g_variant_type_copy (G_VARIANT_TYPE_STRING);
93 return g_variant_type_copy (G_VARIANT_TYPE_OBJECT_PATH);
95 return g_variant_type_copy (G_VARIANT_TYPE_SIGNATURE);
97 return g_variant_type_copy (G_VARIANT_TYPE_BASIC);
99 g_assert_not_reached ();
104 GVariantType *result;
106 switch (g_test_rand_int_range (0, definite ? 5 : 7))
110 GVariantType *element;
112 g_string_append_c (string, 'a');
113 g_string_append (description, "a of ");
114 element = append_type_string (string, description,
116 result = g_variant_type_new_array (element);
117 g_variant_type_free (element);
120 g_assert_true (g_variant_type_is_array (result));
125 GVariantType *element;
127 g_string_append_c (string, 'm');
128 g_string_append (description, "m of ");
129 element = append_type_string (string, description,
131 result = g_variant_type_new_maybe (element);
132 g_variant_type_free (element);
135 g_assert_true (g_variant_type_is_maybe (result));
139 result = append_tuple_type_string (string, description,
142 g_assert_true (g_variant_type_is_tuple (result));
147 GVariantType *key, *value;
149 g_string_append_c (string, '{');
150 g_string_append (description, "e of [");
151 key = append_type_string (string, description, definite, 0);
152 g_string_append (description, ", ");
153 value = append_type_string (string, description, definite, depth);
154 g_string_append_c (description, ']');
155 g_string_append_c (string, '}');
156 result = g_variant_type_new_dict_entry (key, value);
157 g_variant_type_free (key);
158 g_variant_type_free (value);
161 g_assert_true (g_variant_type_is_dict_entry (result));
165 g_string_append_c (string, 'v');
166 g_string_append_c (description, 'V');
167 result = g_variant_type_copy (G_VARIANT_TYPE_VARIANT);
168 g_assert_true (g_variant_type_equal (result, G_VARIANT_TYPE_VARIANT));
172 g_string_append_c (string, '*');
173 g_string_append_c (description, 'S');
174 result = g_variant_type_copy (G_VARIANT_TYPE_ANY);
175 g_assert_true (g_variant_type_equal (result, G_VARIANT_TYPE_ANY));
179 g_string_append_c (string, 'r');
180 g_string_append_c (description, 'R');
181 result = g_variant_type_copy (G_VARIANT_TYPE_TUPLE);
182 g_assert_true (g_variant_type_is_tuple (result));
186 g_assert_not_reached ();
193 static GVariantType *
194 append_tuple_type_string (GString *string,
195 GString *description,
199 GVariantType *result, *other_result;
200 GVariantType **types;
203 g_string_append_c (string, '(');
204 g_string_append (description, "t of [");
206 size = g_test_rand_int_range (0, 20);
207 types = g_new (GVariantType *, size + 1);
209 for (i = 0; i < size; i++)
211 types[i] = append_type_string (string, description, definite, depth);
214 g_string_append (description, ", ");
219 g_string_append_c (description, ']');
220 g_string_append_c (string, ')');
222 result = g_variant_type_new_tuple ((gpointer) types, size);
223 other_result = g_variant_type_new_tuple ((gpointer) types, -1);
224 g_assert_true (g_variant_type_equal (result, other_result));
225 g_variant_type_free (other_result);
226 for (i = 0; i < size; i++)
227 g_variant_type_free (types[i]);
233 /* given a valid type string, make it invalid */
235 invalid_mutation (const gchar *type_string)
237 gboolean have_parens, have_braces;
239 /* it's valid, so '(' implies ')' and same for '{' and '}' */
240 have_parens = strchr (type_string, '(') != NULL;
241 have_braces = strchr (type_string, '{') != NULL;
243 if (have_parens && have_braces && randomly (0.3))
245 /* swap a paren and a brace */
251 new = g_strdup (type_string);
261 /* count number of parens/braces */
262 while ((pp = strchr (pp + 1, p))) np++;
263 while ((bp = strchr (bp + 1, b))) nb++;
265 /* randomly pick one of each */
266 np = g_test_rand_int_range (0, np) + 1;
267 nb = g_test_rand_int_range (0, nb) + 1;
271 while (np--) pp = strchr (pp + 1, p);
272 while (nb--) bp = strchr (bp + 1, b);
275 g_assert_true (*bp == b && *pp == p);
282 if ((have_parens || have_braces) && randomly (0.3))
284 /* drop a paren/brace */
291 if (randomly (0.5)) p = '('; else p = ')';
293 if (randomly (0.5)) p = '{'; else p = '}';
295 new = g_strdup (type_string);
299 while ((pp = strchr (pp + 1, p))) np++;
300 np = g_test_rand_int_range (0, np) + 1;
302 while (np--) pp = strchr (pp + 1, p);
303 g_assert_cmpint (*pp, ==, p);
314 /* else, perform a random mutation at a random point */
322 /* insert a paren/brace */
324 if (randomly (0.5)) p = '('; else p = ')';
326 if (randomly (0.5)) p = '{'; else p = '}';
328 else if (randomly (0.5))
331 p = INVALIDS[g_test_rand_int_range (0, N_INVALIDS)];
340 length = strlen (type_string);
341 new = g_malloc (length + 2);
342 n = g_test_rand_int_range (0, length);
343 memcpy (new, type_string, n);
345 memcpy (new + n + 1, type_string + n, length - n);
346 new[length + 1] = '\0';
352 /* describe a type using the same language as is generated
353 * while generating the type with append_type_string
356 describe_type (const GVariantType *type)
360 if (g_variant_type_is_container (type))
362 g_assert_false (g_variant_type_is_basic (type));
364 if (g_variant_type_is_array (type))
366 gchar *subtype = describe_type (g_variant_type_element (type));
367 result = g_strdup_printf ("a of %s", subtype);
370 else if (g_variant_type_is_maybe (type))
372 gchar *subtype = describe_type (g_variant_type_element (type));
373 result = g_strdup_printf ("m of %s", subtype);
376 else if (g_variant_type_is_tuple (type))
378 if (!g_variant_type_equal (type, G_VARIANT_TYPE_TUPLE))
380 const GVariantType *sub;
384 string = g_string_new ("t of [");
386 length = g_variant_type_n_items (type);
387 sub = g_variant_type_first (type);
388 for (i = 0; i < length; i++)
390 gchar *subtype = describe_type (sub);
391 g_string_append (string, subtype);
394 if ((sub = g_variant_type_next (sub)))
395 g_string_append (string, ", ");
398 g_string_append_c (string, ']');
400 result = g_string_free (string, FALSE);
403 result = g_strdup ("R");
405 else if (g_variant_type_is_dict_entry (type))
407 gchar *key, *value, *key2, *value2;
409 key = describe_type (g_variant_type_key (type));
410 value = describe_type (g_variant_type_value (type));
411 key2 = describe_type (g_variant_type_first (type));
412 value2 = describe_type (
413 g_variant_type_next (g_variant_type_first (type)));
414 g_assert_null (g_variant_type_next (g_variant_type_next (
415 g_variant_type_first (type))));
416 g_assert_cmpstr (key, ==, key2);
417 g_assert_cmpstr (value, ==, value2);
418 result = g_strjoin ("", "e of [", key, ", ", value, "]", NULL);
424 else if (g_variant_type_equal (type, G_VARIANT_TYPE_VARIANT))
426 result = g_strdup ("V");
429 g_assert_not_reached ();
433 if (g_variant_type_is_definite (type))
435 g_assert_true (g_variant_type_is_basic (type));
437 if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN))
438 result = g_strdup ("b");
439 else if (g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
440 result = g_strdup ("y");
441 else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT16))
442 result = g_strdup ("n");
443 else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT16))
444 result = g_strdup ("q");
445 else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32))
446 result = g_strdup ("i");
447 else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT32))
448 result = g_strdup ("u");
449 else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT64))
450 result = g_strdup ("x");
451 else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT64))
452 result = g_strdup ("t");
453 else if (g_variant_type_equal (type, G_VARIANT_TYPE_HANDLE))
454 result = g_strdup ("h");
455 else if (g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
456 result = g_strdup ("d");
457 else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING))
458 result = g_strdup ("s");
459 else if (g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH))
460 result = g_strdup ("o");
461 else if (g_variant_type_equal (type, G_VARIANT_TYPE_SIGNATURE))
462 result = g_strdup ("g");
464 g_assert_not_reached ();
468 if (g_variant_type_equal (type, G_VARIANT_TYPE_ANY))
470 result = g_strdup ("S");
472 else if (g_variant_type_equal (type, G_VARIANT_TYPE_BASIC))
474 result = g_strdup ("?");
477 g_assert_not_reached ();
484 /* given a type string, replace one of the indefinite type characters in
485 * it with a matching type (possibly the same type).
488 generate_subtype (const gchar *type_string)
490 GVariantType *replacement;
491 GString *result, *junk;
495 result = g_string_new (NULL);
496 junk = g_string_new (NULL);
498 /* count the number of indefinite type characters */
499 for (length = 0; type_string[length]; length++)
500 n += type_string[length] == 'r' ||
501 type_string[length] == '?' ||
502 type_string[length] == '*';
503 /* length now is strlen (type_string) */
505 /* pick one at random to replace */
506 n = g_test_rand_int_range (0, n) + 1;
510 while (n--) l += strcspn (type_string + l + 1, "r?*") + 1;
511 g_assert_true (type_string[l] == 'r' ||
512 type_string[l] == '?' ||
513 type_string[l] == '*');
515 /* store up to that point in a GString */
516 g_string_append_len (result, type_string, l);
518 /* then store the replacement in the GString */
519 if (type_string[l] == 'r')
520 replacement = append_tuple_type_string (result, junk, FALSE, 3);
522 else if (type_string[l] == '?')
523 replacement = append_type_string (result, junk, FALSE, 0);
525 else if (type_string[l] == '*')
526 replacement = append_type_string (result, junk, FALSE, 3);
529 g_assert_not_reached ();
531 /* ensure the replacement has the proper type */
532 g_assert_true (g_variant_type_is_subtype_of (replacement,
533 (gpointer) &type_string[l]));
535 /* store the rest from the original type string */
536 g_string_append (result, type_string + l + 1);
538 g_variant_type_free (replacement);
539 g_string_free (junk, TRUE);
541 return g_string_free (result, FALSE);
546 const GVariantType *type;
547 struct typestack *parent;
550 /* given an indefinite type string, replace one of the indefinite
551 * characters in it with a matching type and ensure that the result is a
552 * subtype of the original. repeat.
555 subtype_check (const gchar *type_string,
556 struct typestack *parent_ts)
558 struct typestack ts, *node;
562 subtype = generate_subtype (type_string);
564 ts.type = G_VARIANT_TYPE (subtype);
565 ts.parent = parent_ts;
567 for (node = &ts; node; node = node->parent)
569 /* this type should be a subtype of each parent type */
570 g_assert_true (g_variant_type_is_subtype_of (ts.type, node->type));
572 /* it should only be a supertype when it is exactly equal */
573 g_assert_true (g_variant_type_is_subtype_of (node->type, ts.type) ==
574 g_variant_type_equal (ts.type, node->type));
579 if (!g_variant_type_is_definite (ts.type) && depth < 5)
581 /* the type is still indefinite and we haven't repeated too many
582 * times. go once more.
585 subtype_check (subtype, &ts);
592 test_gvarianttype (void)
596 for (i = 0; i < 2000; i++)
598 GString *type_string, *description;
599 GVariantType *type, *other_type;
600 const GVariantType *ctype;
604 type_string = g_string_new (NULL);
605 description = g_string_new (NULL);
607 /* generate a random type, its type string and a description
609 * exercises type constructor functions and g_variant_type_copy()
611 type = append_type_string (type_string, description, FALSE, 6);
613 /* convert the type string to a type and ensure that it is equal
614 * to the one produced with the type constructor routines
616 ctype = G_VARIANT_TYPE (type_string->str);
617 g_assert_true (g_variant_type_equal (ctype, type));
618 g_assert_cmpuint (g_variant_type_hash (ctype), ==, g_variant_type_hash (type));
619 g_assert_true (g_variant_type_is_subtype_of (ctype, type));
620 g_assert_true (g_variant_type_is_subtype_of (type, ctype));
622 /* check if the type is indefinite */
623 if (!g_variant_type_is_definite (type))
625 struct typestack ts = { type, NULL };
627 /* if it is indefinite, then replace one of the indefinite
628 * characters with a matching type and ensure that the result
629 * is a subtype of the original type. repeat.
631 subtype_check (type_string->str, &ts);
634 /* ensure that no indefinite characters appear */
635 g_assert_cmpint (strcspn (type_string->str, "r?*"), ==, type_string->len);
638 /* describe the type.
640 * exercises the type iterator interface
642 desc = describe_type (type);
644 /* make sure the description matches */
645 g_assert_cmpstr (desc, ==, description->str);
648 /* make an invalid mutation to the type and make sure the type
649 * validation routines catch it */
650 invalid = invalid_mutation (type_string->str);
651 g_assert_true (g_variant_type_string_is_valid (type_string->str));
652 g_assert_false (g_variant_type_string_is_valid (invalid));
655 /* concatenate another type to the type string and ensure that
656 * the result is recognised as being invalid
658 other_type = append_type_string (type_string, description, FALSE, 2);
660 g_string_free (description, TRUE);
661 g_string_free (type_string, TRUE);
662 g_variant_type_free (other_type);
663 g_variant_type_free (type);
667 /* Test that scanning a deeply recursive type string doesn’t exhaust our
668 * stack space (which it would if the type string scanner was recursive). */
670 test_gvarianttype_string_scan_recursion_tuple (void)
672 gchar *type_string = NULL;
673 gsize type_string_len = 1000001; /* not including nul terminator */
676 /* Build a long type string of ‘((…u…))’. */
677 type_string = g_new0 (gchar, type_string_len + 1);
678 for (i = 0; i < type_string_len; i++)
680 if (i < type_string_len / 2)
681 type_string[i] = '(';
682 else if (i == type_string_len / 2)
683 type_string[i] = 'u';
685 type_string[i] = ')';
688 /* Goes (way) over allowed recursion limit. */
689 g_assert_false (g_variant_type_string_is_valid (type_string));
691 g_free (type_string);
694 /* Same as above, except with an array rather than a tuple. */
696 test_gvarianttype_string_scan_recursion_array (void)
698 gchar *type_string = NULL;
699 gsize type_string_len = 1000001; /* not including nul terminator */
702 /* Build a long type string of ‘aaa…aau’. */
703 type_string = g_new0 (gchar, type_string_len + 1);
704 for (i = 0; i < type_string_len; i++)
706 if (i < type_string_len - 1)
707 type_string[i] = 'a';
709 type_string[i] = 'u';
712 /* Goes (way) over allowed recursion limit. */
713 g_assert_false (g_variant_type_string_is_valid (type_string));
715 g_free (type_string);
718 #define ALIGNED(x, y) (((x + (y - 1)) / y) * y)
720 /* do our own calculation of the fixed_size and alignment of a type
721 * using a simple algorithm to make sure the "fancy" one in the
722 * implementation is correct.
725 calculate_type_info (const GVariantType *type,
729 if (g_variant_type_is_array (type) ||
730 g_variant_type_is_maybe (type))
732 calculate_type_info (g_variant_type_element (type), NULL, alignment);
737 else if (g_variant_type_is_tuple (type) ||
738 g_variant_type_is_dict_entry (type))
740 if (g_variant_type_n_items (type))
742 const GVariantType *sub;
751 sub = g_variant_type_first (type);
757 calculate_type_info (sub, &this_fs, &this_al);
759 al = MAX (al, this_al);
769 size = ALIGNED (size, this_al);
773 while ((sub = g_variant_type_next (sub)));
775 size = ALIGNED (size, al);
796 if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN) ||
797 g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
802 else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT16) ||
803 g_variant_type_equal (type, G_VARIANT_TYPE_UINT16))
808 else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32) ||
809 g_variant_type_equal (type, G_VARIANT_TYPE_UINT32) ||
810 g_variant_type_equal (type, G_VARIANT_TYPE_HANDLE))
815 else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT64) ||
816 g_variant_type_equal (type, G_VARIANT_TYPE_UINT64) ||
817 g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
821 else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING) ||
822 g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH) ||
823 g_variant_type_equal (type, G_VARIANT_TYPE_SIGNATURE))
828 else if (g_variant_type_equal (type, G_VARIANT_TYPE_VARIANT))
834 g_assert_not_reached ();
844 /* same as the describe_type() function above, but iterates over
845 * typeinfo instead of types.
848 describe_info (GVariantTypeInfo *info)
852 switch (g_variant_type_info_get_type_char (info))
854 case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
858 element = describe_info (g_variant_type_info_element (info));
859 result = g_strdup_printf ("m of %s", element);
864 case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
868 element = describe_info (g_variant_type_info_element (info));
869 result = g_strdup_printf ("a of %s", element);
874 case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
876 const gchar *sep = "";
880 string = g_string_new ("t of [");
881 length = g_variant_type_info_n_members (info);
883 for (i = 0; i < length; i++)
885 const GVariantMemberInfo *minfo;
888 g_string_append (string, sep);
891 minfo = g_variant_type_info_member_info (info, i);
892 subtype = describe_info (minfo->type_info);
893 g_string_append (string, subtype);
897 g_string_append_c (string, ']');
899 result = g_string_free (string, FALSE);
903 case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
905 const GVariantMemberInfo *keyinfo, *valueinfo;
908 g_assert_cmpint (g_variant_type_info_n_members (info), ==, 2);
909 keyinfo = g_variant_type_info_member_info (info, 0);
910 valueinfo = g_variant_type_info_member_info (info, 1);
911 key = describe_info (keyinfo->type_info);
912 value = describe_info (valueinfo->type_info);
913 result = g_strjoin ("", "e of [", key, ", ", value, "]", NULL);
919 case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
920 result = g_strdup ("V");
924 result = g_strdup (g_variant_type_info_get_type_string (info));
925 g_assert_cmpint (strlen (result), ==, 1);
932 /* check that the O(1) method of calculating offsets meshes with the
933 * results of simple iteration.
936 check_offsets (GVariantTypeInfo *info,
937 const GVariantType *type)
939 gsize flavour, length;
941 length = g_variant_type_info_n_members (info);
942 g_assert_cmpuint (length, ==, g_variant_type_n_items (type));
944 /* the 'flavour' is the low order bits of the ending point of
945 * variable-size items in the tuple. this lets us test that the type
946 * info is correct for various starting alignments.
948 for (flavour = 0; flavour < 8; flavour++)
950 const GVariantType *subtype;
951 gsize last_offset_index;
956 subtype = g_variant_type_first (type);
957 last_offset_index = -1;
961 /* go through the tuple, keeping track of our position */
962 for (i = 0; i < length; i++)
967 calculate_type_info (subtype, &fixed_size, &alignment);
969 position = ALIGNED (position, alignment);
971 /* compare our current aligned position (ie: the start of this
972 * item) to the start offset that would be calculated if we
976 const GVariantMemberInfo *member;
979 member = g_variant_type_info_member_info (info, i);
980 g_assert_cmpint (member->i, ==, last_offset_index);
982 /* do the calculation using the typeinfo */
988 /* did we reach the same spot? */
989 g_assert_cmpint (start, ==, position);
994 /* fixed size. add that size. */
995 position += fixed_size;
999 /* variable size. do the flavouring. */
1000 while ((position & 0x7) != flavour)
1003 /* and store the offset, just like it would be in the
1006 last_offset = position;
1007 last_offset_index++;
1011 subtype = g_variant_type_next (subtype);
1014 /* make sure we used up exactly all the types */
1015 g_assert_null (subtype);
1020 test_gvarianttypeinfo (void)
1024 for (i = 0; i < 2000; i++)
1026 GString *type_string, *description;
1027 gsize fixed_size1, fixed_size2;
1028 guint alignment1, alignment2;
1029 GVariantTypeInfo *info;
1033 type_string = g_string_new (NULL);
1034 description = g_string_new (NULL);
1037 type = append_type_string (type_string, description, TRUE, 6);
1039 /* create a typeinfo for it */
1040 info = g_variant_type_info_get (type);
1042 /* make sure the typeinfo has the right type string */
1043 g_assert_cmpstr (g_variant_type_info_get_type_string (info), ==,
1046 /* calculate the alignment and fixed size, compare to the
1047 * typeinfo's calculations
1049 calculate_type_info (type, &fixed_size1, &alignment1);
1050 g_variant_type_info_query (info, &alignment2, &fixed_size2);
1051 g_assert_cmpint (fixed_size1, ==, fixed_size2);
1052 g_assert_cmpint (alignment1, ==, alignment2 + 1);
1054 /* test the iteration functions over typeinfo structures by
1055 * "describing" the typeinfo and verifying equality.
1057 desc = describe_info (info);
1058 g_assert_cmpstr (desc, ==, description->str);
1060 /* do extra checks for containers */
1061 if (g_variant_type_is_array (type) ||
1062 g_variant_type_is_maybe (type))
1064 const GVariantType *element;
1068 element = g_variant_type_element (type);
1069 calculate_type_info (element, &efs1, &ea1);
1070 g_variant_type_info_query_element (info, &ea2, &efs2);
1071 g_assert_cmpint (efs1, ==, efs2);
1072 g_assert_cmpint (ea1, ==, ea2 + 1);
1074 g_assert_cmpint (ea1, ==, alignment1);
1075 g_assert_cmpint (0, ==, fixed_size1);
1077 else if (g_variant_type_is_tuple (type) ||
1078 g_variant_type_is_dict_entry (type))
1080 /* make sure the "magic constants" are working */
1081 check_offsets (info, type);
1084 g_string_free (type_string, TRUE);
1085 g_string_free (description, TRUE);
1086 g_variant_type_info_unref (info);
1087 g_variant_type_free (type);
1091 g_variant_type_info_assert_no_infos ();
1094 #define MAX_FIXED_MULTIPLIER 256
1095 #define MAX_INSTANCE_SIZE 1024
1096 #define MAX_ARRAY_CHILDREN 128
1097 #define MAX_TUPLE_CHILDREN 128
1099 /* this function generates a random type such that all characteristics
1100 * that are "interesting" to the serializer are tested.
1102 * this basically means:
1103 * - test different alignments
1104 * - test variable sized items and fixed sized items
1105 * - test different fixed sizes
1108 random_type_string (void)
1110 const guchar base_types[] = "ynix";
1113 base_type = base_types[g_test_rand_int_range (0, 4)];
1115 if (g_test_rand_bit ())
1116 /* construct a fixed-sized type */
1118 char type_string[MAX_FIXED_MULTIPLIER];
1122 multiplier = g_test_rand_int_range (1, sizeof type_string - 1);
1124 type_string[i++] = '(';
1125 while (multiplier--)
1126 type_string[i++] = base_type;
1127 type_string[i++] = ')';
1129 return g_strndup (type_string, i);
1132 /* construct a variable-sized type */
1134 char type_string[2] = { 'a', base_type };
1136 return g_strndup (type_string, 2);
1142 GVariantTypeInfo *type_info;
1145 gboolean is_fixed_sized;
1149 #define INSTANCE_MAGIC 1287582829
1153 static RandomInstance *
1154 random_instance (GVariantTypeInfo *type_info)
1156 RandomInstance *instance;
1158 instance = g_slice_new (RandomInstance);
1160 if (type_info == NULL)
1162 gchar *str = random_type_string ();
1163 instance->type_info = g_variant_type_info_get (G_VARIANT_TYPE (str));
1167 instance->type_info = g_variant_type_info_ref (type_info);
1169 instance->seed = g_test_rand_int ();
1171 g_variant_type_info_query (instance->type_info,
1172 &instance->alignment,
1175 instance->is_fixed_sized = instance->size != 0;
1177 if (!instance->is_fixed_sized)
1178 instance->size = g_test_rand_int_range (0, MAX_INSTANCE_SIZE);
1180 instance->magic = INSTANCE_MAGIC;
1186 random_instance_free (RandomInstance *instance)
1188 g_variant_type_info_unref (instance->type_info);
1189 g_slice_free (RandomInstance, instance);
1193 append_instance_size (RandomInstance *instance,
1196 *offset += (-*offset) & instance->alignment;
1197 *offset += instance->size;
1201 random_instance_write (RandomInstance *instance,
1207 g_assert_cmpint ((gsize) buffer & ALIGN_BITS & instance->alignment, ==, 0);
1209 rand = g_rand_new_with_seed (instance->seed);
1210 for (i = 0; i < instance->size; i++)
1211 buffer[i] = g_rand_int (rand);
1216 append_instance_data (RandomInstance *instance,
1219 while (((gsize) *buffer) & instance->alignment)
1220 *(*buffer)++ = '\0';
1222 random_instance_write (instance, *buffer);
1223 *buffer += instance->size;
1227 random_instance_assert (RandomInstance *instance,
1234 g_assert_true (size == 0 || buffer != NULL);
1235 g_assert_cmpint ((gsize) buffer & ALIGN_BITS & instance->alignment, ==, 0);
1236 g_assert_cmpint (size, ==, instance->size);
1238 rand = g_rand_new_with_seed (instance->seed);
1239 for (i = 0; i < instance->size; i++)
1241 guchar byte = g_rand_int (rand);
1243 g_assert_cmpuint (buffer[i], ==, byte);
1247 return i == instance->size;
1251 random_instance_check (RandomInstance *instance,
1258 g_assert_cmpint ((gsize) buffer & ALIGN_BITS & instance->alignment, ==, 0);
1260 if (size != instance->size)
1263 rand = g_rand_new_with_seed (instance->seed);
1264 for (i = 0; i < instance->size; i++)
1265 if (buffer[i] != (guchar) g_rand_int (rand))
1269 return i == instance->size;
1273 random_instance_filler (GVariantSerialised *serialised,
1276 RandomInstance *instance = data;
1278 g_assert_cmpuint (instance->magic, ==, INSTANCE_MAGIC);
1280 if (serialised->type_info == NULL)
1281 serialised->type_info = instance->type_info;
1283 if (serialised->size == 0)
1284 serialised->size = instance->size;
1286 serialised->depth = 0;
1287 serialised->ordered_offsets_up_to = 0;
1288 serialised->checked_offsets_up_to = 0;
1290 g_assert_true (serialised->type_info == instance->type_info);
1291 g_assert_cmpuint (serialised->size, ==, instance->size);
1293 if (serialised->data)
1294 random_instance_write (instance, serialised->data);
1298 calculate_offset_size (gsize body_size,
1304 if (body_size + n_offsets <= G_MAXUINT8)
1307 if (body_size + 2 * n_offsets <= G_MAXUINT16)
1310 if (body_size + 4 * n_offsets <= G_MAXUINT32)
1313 /* the test case won't generate anything bigger */
1314 g_assert_not_reached ();
1318 flavoured_malloc (gsize size, gsize flavour)
1320 g_assert_cmpuint (flavour, <, 8);
1325 return ((gchar *) g_malloc (size + flavour)) + flavour;
1329 flavoured_free (gpointer data,
1334 g_free (((gchar *) data) - flavour);
1338 align_malloc (gsize size)
1342 #ifdef HAVE_POSIX_MEMALIGN
1343 /* posix_memalign() requires the alignment to be a multiple of
1344 * sizeof(void*), and a power of 2. */
1345 if (posix_memalign (&mem, MAX (sizeof (void *), 8), size))
1346 g_error ("posix_memalign failed");
1348 /* NOTE: there may be platforms that lack posix_memalign() and also
1349 * have malloc() that returns non-8-aligned. if so, we need to try
1352 mem = malloc (size);
1359 align_free (gpointer mem)
1365 append_offset (guchar **offset_ptr,
1371 guchar bytes[sizeof (gsize)];
1375 tmpvalue.integer = GSIZE_TO_LE (offset);
1376 memcpy (*offset_ptr, tmpvalue.bytes, offset_size);
1377 *offset_ptr += offset_size;
1381 prepend_offset (guchar **offset_ptr,
1387 guchar bytes[sizeof (gsize)];
1391 *offset_ptr -= offset_size;
1392 tmpvalue.integer = GSIZE_TO_LE (offset);
1393 memcpy (*offset_ptr, tmpvalue.bytes, offset_size);
1399 GVariantTypeInfo *type_info;
1400 RandomInstance *instance;
1404 instance = random_instance (NULL);
1407 const gchar *element;
1410 element = g_variant_type_info_get_type_string (instance->type_info);
1411 tmp = g_strdup_printf ("m%s", element);
1412 type_info = g_variant_type_info_get (G_VARIANT_TYPE (tmp));
1416 needed_size = g_variant_serialiser_needed_size (type_info,
1417 random_instance_filler,
1419 g_assert_cmpint (needed_size, ==, 0);
1421 needed_size = g_variant_serialiser_needed_size (type_info,
1422 random_instance_filler,
1423 (gpointer *) &instance, 1);
1425 if (instance->is_fixed_sized)
1426 g_assert_cmpint (needed_size, ==, instance->size);
1428 g_assert_cmpint (needed_size, ==, instance->size + 1);
1433 ptr = data = align_malloc (needed_size);
1434 append_instance_data (instance, &ptr);
1436 if (!instance->is_fixed_sized)
1439 g_assert_cmpint (ptr - data, ==, needed_size);
1446 alignment = (instance->alignment & ALIGN_BITS) + 1;
1448 for (flavour = 0; flavour < 8; flavour += alignment)
1450 GVariantSerialised serialised = { 0, };
1451 GVariantSerialised child;
1453 serialised.type_info = type_info;
1454 serialised.data = flavoured_malloc (needed_size, flavour);
1455 serialised.size = needed_size;
1456 serialised.depth = 0;
1457 serialised.ordered_offsets_up_to = 0;
1458 serialised.checked_offsets_up_to = 0;
1460 g_variant_serialiser_serialise (serialised,
1461 random_instance_filler,
1462 (gpointer *) &instance, 1);
1464 child = g_variant_serialised_get_child (serialised, 0);
1465 g_assert_true (child.type_info == instance->type_info);
1466 if (child.data != NULL) /* could be NULL if element is non-normal */
1467 random_instance_assert (instance, child.data, child.size);
1468 g_variant_type_info_unref (child.type_info);
1470 flavoured_free (serialised.data, flavour);
1474 g_variant_type_info_unref (type_info);
1475 random_instance_free (instance);
1484 for (i = 0; i < 1000; i++)
1487 g_variant_type_info_assert_no_infos ();
1493 GVariantTypeInfo *element_info;
1494 GVariantTypeInfo *array_info;
1495 RandomInstance **instances;
1502 gchar *element_type, *array_type;
1504 element_type = random_type_string ();
1505 array_type = g_strdup_printf ("a%s", element_type);
1507 element_info = g_variant_type_info_get (G_VARIANT_TYPE (element_type));
1508 array_info = g_variant_type_info_get (G_VARIANT_TYPE (array_type));
1509 g_assert_true (g_variant_type_info_element (array_info) == element_info);
1511 g_free (element_type);
1512 g_free (array_type);
1518 n_children = g_test_rand_int_range (0, MAX_ARRAY_CHILDREN);
1519 instances = g_new (RandomInstance *, n_children);
1520 for (i = 0; i < n_children; i++)
1521 instances[i] = random_instance (element_info);
1524 needed_size = g_variant_serialiser_needed_size (array_info,
1525 random_instance_filler,
1526 (gpointer *) instances,
1530 gsize element_fixed_size;
1531 gsize body_size = 0;
1534 for (i = 0; i < n_children; i++)
1535 append_instance_size (instances[i], &body_size);
1537 g_variant_type_info_query (element_info, NULL, &element_fixed_size);
1539 if (!element_fixed_size)
1541 offset_size = calculate_offset_size (body_size, n_children);
1543 if (offset_size == 0)
1549 g_assert_cmpint (needed_size, ==, body_size + n_children * offset_size);
1553 guchar *offset_ptr, *body_ptr;
1556 body_ptr = data = align_malloc (needed_size);
1557 offset_ptr = body_ptr + needed_size - offset_size * n_children;
1559 for (i = 0; i < n_children; i++)
1561 append_instance_data (instances[i], &body_ptr);
1562 append_offset (&offset_ptr, body_ptr - data, offset_size);
1565 g_assert_true (body_ptr == data + needed_size - offset_size * n_children);
1566 g_assert_true (offset_ptr == data + needed_size);
1574 g_variant_type_info_query (array_info, &alignment, NULL);
1575 alignment = (alignment & ALIGN_BITS) + 1;
1577 for (flavour = 0; flavour < 8; flavour += alignment)
1579 GVariantSerialised serialised = { 0, };
1581 serialised.type_info = array_info;
1582 serialised.data = flavoured_malloc (needed_size, flavour);
1583 serialised.size = needed_size;
1584 serialised.depth = 0;
1585 serialised.ordered_offsets_up_to = 0;
1586 serialised.checked_offsets_up_to = 0;
1588 g_variant_serialiser_serialise (serialised, random_instance_filler,
1589 (gpointer *) instances, n_children);
1591 if (serialised.size)
1592 g_assert_cmpint (memcmp (serialised.data, data, serialised.size), ==, 0);
1594 g_assert_cmpuint (g_variant_serialised_n_children (serialised), ==, n_children);
1596 for (i = 0; i < n_children; i++)
1598 GVariantSerialised child;
1600 child = g_variant_serialised_get_child (serialised, i);
1601 g_assert_true (child.type_info == instances[i]->type_info);
1602 if (child.data != NULL) /* could be NULL if element is non-normal */
1603 random_instance_assert (instances[i], child.data, child.size);
1604 g_variant_type_info_unref (child.type_info);
1607 flavoured_free (serialised.data, flavour);
1614 for (i = 0; i < n_children; i++)
1615 random_instance_free (instances[i]);
1619 g_variant_type_info_unref (element_info);
1620 g_variant_type_info_unref (array_info);
1629 for (i = 0; i < 100; i++)
1632 g_variant_type_info_assert_no_infos ();
1638 GVariantTypeInfo *type_info;
1639 RandomInstance **instances;
1640 gboolean fixed_size;
1647 n_children = g_test_rand_int_range (0, MAX_TUPLE_CHILDREN);
1648 instances = g_new (RandomInstance *, n_children);
1651 GString *type_string;
1657 type_string = g_string_new ("(");
1658 for (i = 0; i < n_children; i++)
1662 instances[i] = random_instance (NULL);
1664 alignment |= instances[i]->alignment;
1665 if (!instances[i]->is_fixed_sized)
1668 str = g_variant_type_info_get_type_string (instances[i]->type_info);
1669 g_string_append (type_string, str);
1671 g_string_append_c (type_string, ')');
1673 type_info = g_variant_type_info_get (G_VARIANT_TYPE (type_string->str));
1674 g_string_free (type_string, TRUE);
1677 needed_size = g_variant_serialiser_needed_size (type_info,
1678 random_instance_filler,
1679 (gpointer *) instances,
1682 gsize body_size = 0;
1686 for (i = 0; i < n_children; i++)
1688 append_instance_size (instances[i], &body_size);
1690 if (i != n_children - 1 && !instances[i]->is_fixed_sized)
1696 body_size += (-body_size) & alignment;
1698 g_assert_true ((body_size == 0) == (n_children == 0));
1699 if (n_children == 0)
1703 offset_size = calculate_offset_size (body_size, offsets);
1704 g_assert_cmpint (needed_size, ==, body_size + offsets * offset_size);
1712 body_ptr = data = align_malloc (needed_size);
1713 ofs_ptr = body_ptr + needed_size;
1715 for (i = 0; i < n_children; i++)
1717 append_instance_data (instances[i], &body_ptr);
1719 if (i != n_children - 1 && !instances[i]->is_fixed_sized)
1720 prepend_offset (&ofs_ptr, body_ptr - data, offset_size);
1725 while (((gsize) body_ptr) & alignment)
1728 g_assert_true ((body_ptr == data) == (n_children == 0));
1729 if (n_children == 0)
1735 g_assert_true (body_ptr == ofs_ptr);
1742 alignment = (alignment & ALIGN_BITS) + 1;
1744 for (flavour = 0; flavour < 8; flavour += alignment)
1746 GVariantSerialised serialised = { 0, };
1748 serialised.type_info = type_info;
1749 serialised.data = flavoured_malloc (needed_size, flavour);
1750 serialised.size = needed_size;
1751 serialised.depth = 0;
1752 serialised.ordered_offsets_up_to = 0;
1753 serialised.checked_offsets_up_to = 0;
1755 g_variant_serialiser_serialise (serialised, random_instance_filler,
1756 (gpointer *) instances, n_children);
1758 if (serialised.size)
1759 g_assert_cmpint (memcmp (serialised.data, data, serialised.size), ==, 0);
1761 g_assert_cmpuint (g_variant_serialised_n_children (serialised), ==, n_children);
1763 for (i = 0; i < n_children; i++)
1765 GVariantSerialised child;
1767 child = g_variant_serialised_get_child (serialised, i);
1768 g_assert_true (child.type_info == instances[i]->type_info);
1769 if (child.data != NULL) /* could be NULL if element is non-normal */
1770 random_instance_assert (instances[i], child.data, child.size);
1771 g_variant_type_info_unref (child.type_info);
1774 flavoured_free (serialised.data, flavour);
1781 for (i = 0; i < n_children; i++)
1782 random_instance_free (instances[i]);
1786 g_variant_type_info_unref (type_info);
1795 for (i = 0; i < 100; i++)
1798 g_variant_type_info_assert_no_infos ();
1804 GVariantTypeInfo *type_info;
1805 RandomInstance *instance;
1806 const gchar *type_string;
1811 type_info = g_variant_type_info_get (G_VARIANT_TYPE_VARIANT);
1812 instance = random_instance (NULL);
1814 type_string = g_variant_type_info_get_type_string (instance->type_info);
1815 len = strlen (type_string);
1817 needed_size = g_variant_serialiser_needed_size (type_info,
1818 random_instance_filler,
1819 (gpointer *) &instance, 1);
1821 g_assert_cmpint (needed_size, ==, instance->size + 1 + len);
1826 ptr = data = align_malloc (needed_size);
1827 append_instance_data (instance, &ptr);
1829 memcpy (ptr, type_string, len);
1832 g_assert_true (data + needed_size == ptr);
1839 /* variants are always 8-aligned */
1840 alignment = ALIGN_BITS + 1;
1842 for (flavour = 0; flavour < 8; flavour += alignment)
1844 GVariantSerialised serialised = { 0, };
1845 GVariantSerialised child;
1847 serialised.type_info = type_info;
1848 serialised.data = flavoured_malloc (needed_size, flavour);
1849 serialised.size = needed_size;
1850 serialised.depth = 0;
1851 serialised.ordered_offsets_up_to = 0;
1852 serialised.checked_offsets_up_to = 0;
1854 g_variant_serialiser_serialise (serialised, random_instance_filler,
1855 (gpointer *) &instance, 1);
1857 if (serialised.size)
1858 g_assert_cmpint (memcmp (serialised.data, data, serialised.size), ==, 0);
1860 g_assert_cmpuint (g_variant_serialised_n_children (serialised), ==, 1);
1862 child = g_variant_serialised_get_child (serialised, 0);
1863 g_assert_true (child.type_info == instance->type_info);
1864 random_instance_check (instance, child.data, child.size);
1866 g_variant_type_info_unref (child.type_info);
1867 flavoured_free (serialised.data, flavour);
1871 g_variant_type_info_unref (type_info);
1872 random_instance_free (instance);
1877 test_variants (void)
1881 for (i = 0; i < 100; i++)
1884 g_variant_type_info_assert_no_infos ();
1897 #define is_objpath is_string | 2
1898 #define is_sig is_string | 4
1900 { is_nval, 0, NULL },
1901 { is_nval, 13, "hello\xffworld!" },
1902 { is_string, 13, "hello world!" },
1903 { is_nval, 13, "hello world\0" },
1904 { is_nval, 13, "hello\0world!" },
1905 { is_nval, 12, "hello world!" },
1906 { is_nval, 13, "hello world!\xff" },
1908 { is_objpath, 2, "/" },
1909 { is_objpath, 3, "/a" },
1910 { is_string, 3, "//" },
1911 { is_objpath, 11, "/some/path" },
1912 { is_string, 12, "/some/path/" },
1913 { is_nval, 11, "/some\0path" },
1914 { is_string, 11, "/some\\path" },
1915 { is_string, 12, "/some//path" },
1916 { is_string, 12, "/some-/path" },
1920 { is_sig, 5, "(si)" },
1921 { is_string, 4, "(si" },
1922 { is_string, 2, "*" },
1923 { is_sig, 3, "ai" },
1924 { is_string, 3, "mi" },
1925 { is_string, 2, "r" },
1926 { is_sig, 15, "(yyy{sv}ssiai)" },
1927 { is_string, 16, "(yyy{yv}ssiai))" },
1928 { is_string, 15, "(yyy{vv}ssiai)" },
1929 { is_string, 15, "(yyy{sv)ssiai}" }
1933 for (i = 0; i < G_N_ELEMENTS (test_cases); i++)
1937 flags = g_variant_serialiser_is_string (test_cases[i].data,
1941 flags |= g_variant_serialiser_is_object_path (test_cases[i].data,
1945 flags |= g_variant_serialiser_is_signature (test_cases[i].data,
1949 g_assert_cmpuint (flags, ==, test_cases[i].flags);
1953 typedef struct _TreeInstance TreeInstance;
1954 struct _TreeInstance
1956 GVariantTypeInfo *info;
1958 TreeInstance **children;
1969 static GVariantType *
1970 make_random_definite_type (int depth)
1972 GString *description;
1973 GString *type_string;
1976 description = g_string_new (NULL);
1977 type_string = g_string_new (NULL);
1978 type = append_type_string (type_string, description, TRUE, depth);
1979 g_string_free (description, TRUE);
1980 g_string_free (type_string, TRUE);
1986 make_random_string (gchar *string,
1988 const GVariantType *type)
1992 /* create strings that are valid signature strings */
1993 #define good_chars "bynqiuxthdsog"
1995 for (i = 0; i < size - 1; i++)
1996 string[i] = good_chars[g_test_rand_int_range (0, strlen (good_chars))];
1999 /* in case we need an object path, prefix a '/' */
2000 if (*g_variant_type_peek_string (type) == 'o')
2006 static TreeInstance *
2007 tree_instance_new (const GVariantType *type,
2010 const GVariantType *child_type = NULL;
2011 GVariantType *mytype = NULL;
2012 TreeInstance *instance;
2013 gboolean is_tuple_type;
2016 type = mytype = make_random_definite_type (depth);
2018 instance = g_slice_new (TreeInstance);
2019 instance->info = g_variant_type_info_get (type);
2020 instance->children = NULL;
2021 instance->n_children = 0;
2022 instance->data_size = 0;
2024 is_tuple_type = FALSE;
2026 switch (*g_variant_type_peek_string (type))
2028 case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
2029 instance->n_children = g_test_rand_int_range (0, 2);
2030 child_type = g_variant_type_element (type);
2033 case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
2034 instance->n_children = g_test_rand_int_range (0, MAX_ARRAY_CHILDREN);
2035 child_type = g_variant_type_element (type);
2038 case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
2039 case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
2040 instance->n_children = g_variant_type_n_items (type);
2041 child_type = g_variant_type_first (type);
2042 is_tuple_type = TRUE;
2045 case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
2046 instance->n_children = 1;
2051 instance->data.integer = g_test_rand_int_range (0, 2);
2052 instance->data_size = 1;
2056 instance->data.integer = g_test_rand_int ();
2057 instance->data_size = 1;
2061 instance->data.integer = g_test_rand_int ();
2062 instance->data_size = 2;
2065 case 'i': case 'u': case 'h':
2066 instance->data.integer = g_test_rand_int ();
2067 instance->data_size = 4;
2071 instance->data.integer = g_test_rand_int ();
2072 instance->data.integer <<= 32;
2073 instance->data.integer |= (guint32) g_test_rand_int ();
2074 instance->data_size = 8;
2078 instance->data.floating = g_test_rand_double ();
2079 instance->data_size = 8;
2082 case 's': case 'o': case 'g':
2083 instance->data_size = g_test_rand_int_range (10, 200);
2084 make_random_string (instance->data.string, instance->data_size, type);
2088 if (instance->data_size == 0)
2089 /* no data -> it is a container */
2093 instance->children = g_new (TreeInstance *, instance->n_children);
2095 for (i = 0; i < instance->n_children; i++)
2097 instance->children[i] = tree_instance_new (child_type, depth - 1);
2100 child_type = g_variant_type_next (child_type);
2103 g_assert_true (!is_tuple_type || child_type == NULL);
2106 g_variant_type_free (mytype);
2112 tree_instance_free (TreeInstance *instance)
2116 g_variant_type_info_unref (instance->info);
2117 for (i = 0; i < instance->n_children; i++)
2118 tree_instance_free (instance->children[i]);
2119 g_free (instance->children);
2120 g_slice_free (TreeInstance, instance);
2123 static gboolean i_am_writing_byteswapped;
2126 tree_filler (GVariantSerialised *serialised,
2129 TreeInstance *instance = data;
2131 if (serialised->type_info == NULL)
2132 serialised->type_info = instance->info;
2134 serialised->depth = 0;
2136 if (instance->data_size == 0)
2137 /* is a container */
2139 if (serialised->size == 0)
2141 g_variant_serialiser_needed_size (instance->info, tree_filler,
2142 (gpointer *) instance->children,
2143 instance->n_children);
2145 if (serialised->data)
2146 g_variant_serialiser_serialise (*serialised, tree_filler,
2147 (gpointer *) instance->children,
2148 instance->n_children);
2153 if (serialised->size == 0)
2154 serialised->size = instance->data_size;
2156 if (serialised->data)
2158 switch (instance->data_size)
2161 *serialised->data = instance->data.integer;
2166 guint16 value = instance->data.integer;
2168 if (i_am_writing_byteswapped)
2169 value = GUINT16_SWAP_LE_BE (value);
2171 *(guint16 *) serialised->data = value;
2177 guint32 value = instance->data.integer;
2179 if (i_am_writing_byteswapped)
2180 value = GUINT32_SWAP_LE_BE (value);
2182 *(guint32 *) serialised->data = value;
2188 guint64 value = instance->data.integer;
2190 if (i_am_writing_byteswapped)
2191 value = GUINT64_SWAP_LE_BE (value);
2193 *(guint64 *) serialised->data = value;
2198 memcpy (serialised->data,
2199 instance->data.string,
2200 instance->data_size);
2208 check_tree (TreeInstance *instance,
2209 GVariantSerialised serialised)
2211 if (instance->info != serialised.type_info)
2214 if (instance->data_size == 0)
2215 /* is a container */
2219 if (g_variant_serialised_n_children (serialised) !=
2220 instance->n_children)
2223 for (i = 0; i < instance->n_children; i++)
2225 GVariantSerialised child;
2226 gpointer data = NULL;
2229 child = g_variant_serialised_get_child (serialised, i);
2230 if (child.size && child.data == NULL)
2231 child.data = data = g_malloc0 (child.size);
2232 ok = check_tree (instance->children[i], child);
2233 g_variant_type_info_unref (child.type_info);
2245 switch (instance->data_size)
2248 g_assert_cmpuint (serialised.size, ==, 1);
2249 return *(guint8 *) serialised.data ==
2250 (guint8) instance->data.integer;
2253 g_assert_cmpuint (serialised.size, ==, 2);
2254 return *(guint16 *) serialised.data ==
2255 (guint16) instance->data.integer;
2258 g_assert_cmpuint (serialised.size, ==, 4);
2259 return *(guint32 *) serialised.data ==
2260 (guint32) instance->data.integer;
2263 g_assert_cmpuint (serialised.size, ==, 8);
2264 return *(guint64 *) serialised.data ==
2265 (guint64) instance->data.integer;
2268 if (serialised.size != instance->data_size)
2271 return memcmp (serialised.data,
2272 instance->data.string,
2273 instance->data_size) == 0;
2279 serialise_tree (TreeInstance *tree,
2280 GVariantSerialised *serialised)
2282 GVariantSerialised empty = {0, };
2284 *serialised = empty;
2285 tree_filler (serialised, tree);
2286 serialised->data = g_malloc (serialised->size);
2287 tree_filler (serialised, tree);
2291 test_byteswap (void)
2293 GVariantSerialised one = { 0, }, two = { 0, }, three = { 0, };
2295 GVariant *one_variant = NULL;
2296 GVariant *two_variant = NULL;
2297 GVariant *two_byteswapped = NULL;
2298 GVariant *three_variant = NULL;
2299 GVariant *three_byteswapped = NULL;
2300 guint8 *three_data_copy = NULL;
2301 gsize three_size_copy = 0;
2303 /* Write a tree out twice, once normally and once byteswapped. */
2304 tree = tree_instance_new (NULL, 3);
2305 serialise_tree (tree, &one);
2307 one_variant = g_variant_new_from_data (G_VARIANT_TYPE (g_variant_type_info_get_type_string (one.type_info)),
2308 one.data, one.size, FALSE, NULL, NULL);
2310 i_am_writing_byteswapped = TRUE;
2311 serialise_tree (tree, &two);
2312 serialise_tree (tree, &three);
2313 i_am_writing_byteswapped = FALSE;
2315 /* Swap the first byteswapped one back using the function we want to test. */
2316 two_variant = g_variant_new_from_data (G_VARIANT_TYPE (g_variant_type_info_get_type_string (two.type_info)),
2317 two.data, two.size, FALSE, NULL, NULL);
2318 two_byteswapped = g_variant_byteswap (two_variant);
2320 /* Make the second byteswapped one non-normal (hopefully), and then byteswap
2321 * it back using the function we want to test in its non-normal mode.
2322 * This might not work because it’s not necessarily possible to make an
2323 * arbitrary random variant non-normal. Adding a single zero byte to the end
2324 * often makes something non-normal but still readable. */
2325 three_size_copy = three.size + 1;
2326 three_data_copy = g_malloc (three_size_copy);
2327 memcpy (three_data_copy, three.data, three.size);
2328 three_data_copy[three.size] = '\0';
2330 three_variant = g_variant_new_from_data (G_VARIANT_TYPE (g_variant_type_info_get_type_string (three.type_info)),
2331 three_data_copy, three_size_copy, FALSE, NULL, NULL);
2332 three_byteswapped = g_variant_byteswap (three_variant);
2334 /* Check they’re the same. We can always compare @one_variant and
2335 * @two_byteswapped. We can only compare @two_byteswapped and
2336 * @three_byteswapped if @two_variant and @three_variant are equal: in that
2337 * case, the corruption to @three_variant was enough to make it non-normal but
2338 * not enough to change its value. */
2339 g_assert_cmpvariant (one_variant, two_byteswapped);
2341 if (g_variant_equal (two_variant, three_variant))
2342 g_assert_cmpvariant (two_byteswapped, three_byteswapped);
2344 g_variant_unref (three_byteswapped);
2345 g_variant_unref (three_variant);
2346 g_variant_unref (two_byteswapped);
2347 g_variant_unref (two_variant);
2348 g_variant_unref (one_variant);
2349 tree_instance_free (tree);
2352 g_free (three.data);
2353 g_free (three_data_copy);
2357 test_byteswaps (void)
2361 for (i = 0; i < 200; i++)
2364 g_variant_type_info_assert_no_infos ();
2368 test_serialiser_children (void)
2370 GBytes *data1, *data2;
2371 GVariant *child1, *child2;
2372 GVariantType *mv_type = g_variant_type_new_maybe (G_VARIANT_TYPE_VARIANT);
2373 GVariant *variant, *child;
2375 g_test_bug ("https://gitlab.gnome.org/GNOME/glib/issues/1865");
2376 g_test_summary ("Test that getting a child variant before and after "
2377 "serialisation of the parent works");
2379 /* Construct a variable sized array containing a child which serializes to a
2380 * zero-length bytestring. */
2381 child = g_variant_new_maybe (G_VARIANT_TYPE_VARIANT, NULL);
2382 variant = g_variant_new_array (mv_type, &child, 1);
2384 /* Get the child before serializing. */
2385 child1 = g_variant_get_child_value (variant, 0);
2386 data1 = g_variant_get_data_as_bytes (child1);
2388 /* Serialize the parent variant. */
2389 g_variant_get_data (variant);
2391 /* Get the child again after serializing — this uses a different code path. */
2392 child2 = g_variant_get_child_value (variant, 0);
2393 data2 = g_variant_get_data_as_bytes (child2);
2395 /* Check things are equal. */
2396 g_assert_cmpvariant (child1, child2);
2397 g_assert_true (g_bytes_equal (data1, data2));
2399 g_variant_unref (child2);
2400 g_variant_unref (child1);
2401 g_variant_unref (variant);
2402 g_bytes_unref (data2);
2403 g_bytes_unref (data1);
2404 g_variant_type_free (mv_type);
2408 test_fuzz (gdouble *fuzziness)
2410 GVariantSerialised serialised = { 0, };
2413 /* make an instance */
2414 tree = tree_instance_new (NULL, 3);
2417 serialise_tree (tree, &serialised);
2419 g_assert_true (g_variant_serialised_is_normal (serialised));
2420 g_assert_true (check_tree (tree, serialised));
2422 if (serialised.size)
2424 gboolean fuzzed = FALSE;
2431 for (i = 0; i < serialised.size; i++)
2432 if (randomly (*fuzziness))
2434 serialised.data[i] += g_test_rand_int_range (1, 256);
2439 /* at least one byte in the serialized data has changed.
2441 * this means that at least one of the following is true:
2443 * - the serialized data now represents a different value:
2444 * check_tree() will return FALSE
2446 * - the serialized data is in non-normal form:
2447 * g_variant_serialiser_is_normal() will return FALSE
2449 * we always do both checks to increase exposure of the serializer
2452 a = g_variant_serialised_is_normal (serialised);
2453 b = check_tree (tree, serialised);
2455 g_assert_true (!a || !b);
2458 tree_instance_free (tree);
2459 g_free (serialised.data);
2464 test_fuzzes (gpointer data)
2469 fuzziness = GPOINTER_TO_INT (data) / 100.;
2471 for (i = 0; i < 200; i++)
2472 test_fuzz (&fuzziness);
2474 g_variant_type_info_assert_no_infos ();
2478 tree_instance_get_gvariant (TreeInstance *tree)
2480 const GVariantType *type;
2483 type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
2485 switch (g_variant_type_info_get_type_char (tree->info))
2487 case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
2489 const GVariantType *child_type;
2492 if (tree->n_children)
2493 child = tree_instance_get_gvariant (tree->children[0]);
2497 child_type = g_variant_type_element (type);
2499 if (child != NULL && randomly (0.5))
2502 result = g_variant_new_maybe (child_type, child);
2506 case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
2508 const GVariantType *child_type;
2509 GVariant **children;
2512 children = g_new (GVariant *, tree->n_children);
2513 for (i = 0; i < tree->n_children; i++)
2514 children[i] = tree_instance_get_gvariant (tree->children[i]);
2516 child_type = g_variant_type_element (type);
2518 if (i > 0 && randomly (0.5))
2521 result = g_variant_new_array (child_type, children, tree->n_children);
2526 case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
2528 GVariant **children;
2531 children = g_new (GVariant *, tree->n_children);
2532 for (i = 0; i < tree->n_children; i++)
2533 children[i] = tree_instance_get_gvariant (tree->children[i]);
2535 result = g_variant_new_tuple (children, tree->n_children);
2540 case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
2542 GVariant *key, *val;
2544 g_assert_cmpuint (tree->n_children, ==, 2);
2546 key = tree_instance_get_gvariant (tree->children[0]);
2547 val = tree_instance_get_gvariant (tree->children[1]);
2549 result = g_variant_new_dict_entry (key, val);
2553 case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
2557 g_assert_cmpuint (tree->n_children, ==, 1);
2559 value = tree_instance_get_gvariant (tree->children[0]);
2560 result = g_variant_new_variant (value);
2565 result = g_variant_new_boolean (tree->data.integer > 0);
2569 result = g_variant_new_byte (tree->data.integer);
2573 result = g_variant_new_int16 (tree->data.integer);
2577 result = g_variant_new_uint16 (tree->data.integer);
2581 result = g_variant_new_int32 (tree->data.integer);
2585 result = g_variant_new_uint32 (tree->data.integer);
2589 result = g_variant_new_int64 (tree->data.integer);
2593 result = g_variant_new_uint64 (tree->data.integer);
2597 result = g_variant_new_handle (tree->data.integer);
2601 result = g_variant_new_double (tree->data.floating);
2605 result = g_variant_new_string (tree->data.string);
2609 result = g_variant_new_object_path (tree->data.string);
2613 result = g_variant_new_signature (tree->data.string);
2617 g_assert_not_reached ();
2624 tree_instance_check_gvariant (TreeInstance *tree,
2627 const GVariantType *type;
2629 type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
2630 g_assert_true (g_variant_is_of_type (value, type));
2632 switch (g_variant_type_info_get_type_char (tree->info))
2634 case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
2639 child = g_variant_get_maybe (value);
2641 if (child != NULL && tree->n_children == 1)
2642 equal = tree_instance_check_gvariant (tree->children[0], child);
2643 else if (child == NULL && tree->n_children == 0)
2649 g_variant_unref (child);
2655 case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
2656 case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
2657 case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
2661 if (g_variant_n_children (value) != tree->n_children)
2664 for (i = 0; i < tree->n_children; i++)
2669 child = g_variant_get_child_value (value, i);
2670 equal = tree_instance_check_gvariant (tree->children[i], child);
2671 g_variant_unref (child);
2681 case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
2683 const gchar *str1, *str2;
2687 child = g_variant_get_variant (value);
2688 str1 = g_variant_get_type_string (child);
2689 str2 = g_variant_type_info_get_type_string (tree->children[0]->info);
2690 /* GVariant only keeps one copy of type strings around */
2691 equal = str1 == str2 &&
2692 tree_instance_check_gvariant (tree->children[0], child);
2694 g_variant_unref (child);
2701 return g_variant_get_boolean (value) == (gboolean) tree->data.integer;
2704 return g_variant_get_byte (value) == (guchar) tree->data.integer;
2707 return g_variant_get_int16 (value) == (gint16) tree->data.integer;
2710 return g_variant_get_uint16 (value) == (guint16) tree->data.integer;
2713 return g_variant_get_int32 (value) == (gint32) tree->data.integer;
2716 return g_variant_get_uint32 (value) == (guint32) tree->data.integer;
2719 return g_variant_get_int64 (value) == (gint64) tree->data.integer;
2722 return g_variant_get_uint64 (value) == (guint64) tree->data.integer;
2725 return g_variant_get_handle (value) == (gint32) tree->data.integer;
2729 gdouble floating = g_variant_get_double (value);
2731 return memcmp (&floating, &tree->data.floating, sizeof floating) == 0;
2737 return strcmp (g_variant_get_string (value, NULL),
2738 tree->data.string) == 0;
2741 g_assert_not_reached ();
2746 tree_instance_build_gvariant (TreeInstance *tree,
2747 GVariantBuilder *builder,
2750 const GVariantType *type;
2752 type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
2754 if (g_variant_type_is_container (type))
2758 /* force GVariantBuilder to guess the type half the time */
2759 if (guess_ok && randomly (0.5))
2761 if (g_variant_type_is_array (type) && tree->n_children)
2762 type = G_VARIANT_TYPE_ARRAY;
2764 if (g_variant_type_is_maybe (type) && tree->n_children)
2765 type = G_VARIANT_TYPE_MAYBE;
2767 if (g_variant_type_is_tuple (type))
2768 type = G_VARIANT_TYPE_TUPLE;
2770 if (g_variant_type_is_dict_entry (type))
2771 type = G_VARIANT_TYPE_DICT_ENTRY;
2776 g_variant_builder_open (builder, type);
2778 for (i = 0; i < tree->n_children; i++)
2779 tree_instance_build_gvariant (tree->children[i], builder, guess_ok);
2781 g_variant_builder_close (builder);
2784 g_variant_builder_add_value (builder, tree_instance_get_gvariant (tree));
2789 tree_instance_check_iter (TreeInstance *tree,
2794 value = g_variant_iter_next_value (iter);
2796 if (g_variant_is_container (value))
2800 iter = g_variant_iter_new (value);
2801 g_variant_unref (value);
2803 if (g_variant_iter_n_children (iter) != tree->n_children)
2805 g_variant_iter_free (iter);
2809 for (i = 0; i < tree->n_children; i++)
2810 if (!tree_instance_check_iter (tree->children[i], iter))
2812 g_variant_iter_free (iter);
2816 g_assert_null (g_variant_iter_next_value (iter));
2817 g_variant_iter_free (iter);
2826 equal = tree_instance_check_gvariant (tree, value);
2827 g_variant_unref (value);
2834 test_container (void)
2840 tree = tree_instance_new (NULL, 3);
2841 value = g_variant_ref_sink (tree_instance_get_gvariant (tree));
2843 s1 = g_variant_print (value, TRUE);
2844 g_assert_true (tree_instance_check_gvariant (tree, value));
2846 g_variant_get_data (value);
2848 s2 = g_variant_print (value, TRUE);
2849 g_assert_true (tree_instance_check_gvariant (tree, value));
2851 g_assert_cmpstr (s1, ==, s2);
2853 if (g_variant_is_container (value))
2855 GVariantBuilder builder;
2861 g_variant_builder_init (&builder, G_VARIANT_TYPE_VARIANT);
2862 tree_instance_build_gvariant (tree, &builder, TRUE);
2863 built = g_variant_builder_end (&builder);
2864 g_variant_ref_sink (built);
2865 g_variant_get_data (built);
2866 val = g_variant_get_variant (built);
2868 s3 = g_variant_print (val, TRUE);
2869 g_assert_cmpstr (s1, ==, s3);
2871 g_variant_iter_init (&iter, built);
2872 g_assert_true (tree_instance_check_iter (tree, &iter));
2873 g_assert_null (g_variant_iter_next_value (&iter));
2875 g_variant_unref (built);
2876 g_variant_unref (val);
2880 tree_instance_free (tree);
2881 g_variant_unref (value);
2889 /* Test some different methods of creating strings */
2892 v = g_variant_new_string ("foo");
2893 g_assert_cmpstr (g_variant_get_string (v, NULL), ==, "foo");
2894 g_variant_unref (v);
2897 v = g_variant_new_take_string (g_strdup ("foo"));
2898 g_assert_cmpstr (g_variant_get_string (v, NULL), ==, "foo");
2899 g_variant_unref (v);
2901 v = g_variant_new_printf ("%s %d", "foo", 123);
2902 g_assert_cmpstr (g_variant_get_string (v, NULL), ==, "foo 123");
2903 g_variant_unref (v);
2909 const gchar invalid[] = "hello\xffworld";
2912 /* ensure that the test data is not valid utf8... */
2913 g_assert_false (g_utf8_validate (invalid, -1, NULL));
2915 /* load the data untrusted */
2916 value = g_variant_new_from_data (G_VARIANT_TYPE_STRING,
2917 invalid, sizeof invalid,
2920 /* ensure that the problem is caught and we get valid UTF-8 */
2921 g_assert_true (g_utf8_validate (g_variant_get_string (value, NULL), -1, NULL));
2922 g_variant_unref (value);
2925 /* now load it trusted */
2926 value = g_variant_new_from_data (G_VARIANT_TYPE_STRING,
2927 invalid, sizeof invalid,
2930 /* ensure we get the invalid data (ie: make sure that time wasn't
2931 * wasted on validating data that was marked as trusted)
2933 g_assert_true (g_variant_get_string (value, NULL) == invalid);
2934 g_variant_unref (value);
2938 test_containers (void)
2942 for (i = 0; i < 100; i++)
2947 g_variant_type_info_assert_no_infos ();
2951 test_format_strings (void)
2956 g_assert_true (g_variant_format_string_scan ("i", NULL, &end) && *end == '\0');
2957 g_assert_true (g_variant_format_string_scan ("@i", NULL, &end) && *end == '\0');
2958 g_assert_true (g_variant_format_string_scan ("@ii", NULL, &end) && *end == 'i');
2959 g_assert_true (g_variant_format_string_scan ("^a&s", NULL, &end) && *end == '\0');
2960 g_assert_true (g_variant_format_string_scan ("(^as)", NULL, &end) &&
2962 g_assert_false (g_variant_format_string_scan ("(^s)", NULL, &end));
2963 g_assert_false (g_variant_format_string_scan ("(^a)", NULL, &end));
2964 g_assert_false (g_variant_format_string_scan ("(z)", NULL, &end));
2965 g_assert_false (g_variant_format_string_scan ("az", NULL, &end));
2966 g_assert_false (g_variant_format_string_scan ("{**}", NULL, &end));
2967 g_assert_false (g_variant_format_string_scan ("{@**}", NULL, &end));
2968 g_assert_true (g_variant_format_string_scan ("{@y*}", NULL, &end) &&
2970 g_assert_true (g_variant_format_string_scan ("{yv}", NULL, &end) &&
2972 g_assert_false (g_variant_format_string_scan ("{&?v}", NULL, &end));
2973 g_assert_true (g_variant_format_string_scan ("{@?v}", NULL, &end) &&
2975 g_assert_false (g_variant_format_string_scan ("{&@sv}", NULL, &end));
2976 g_assert_false (g_variant_format_string_scan ("{@&sv}", NULL, &end));
2977 g_assert_true (g_variant_format_string_scan ("{&sv}", NULL, &end) &&
2979 g_assert_false (g_variant_format_string_scan ("{vv}", NULL, &end));
2980 g_assert_false (g_variant_format_string_scan ("{y}", NULL, &end));
2981 g_assert_false (g_variant_format_string_scan ("{yyy}", NULL, &end));
2982 g_assert_false (g_variant_format_string_scan ("{ya}", NULL, &end));
2983 g_assert_true (g_variant_format_string_scan ("&s", NULL, &end) && *end == '\0');
2984 g_assert_false (g_variant_format_string_scan ("&as", NULL, &end));
2985 g_assert_false (g_variant_format_string_scan ("@z", NULL, &end));
2986 g_assert_false (g_variant_format_string_scan ("az", NULL, &end));
2987 g_assert_false (g_variant_format_string_scan ("a&s", NULL, &end));
2989 type = g_variant_format_string_scan_type ("mm(@xy^a&s*?@?)", NULL, &end);
2990 g_assert_true (type && *end == '\0');
2991 g_assert_true (g_variant_type_equal (type, G_VARIANT_TYPE ("mm(xyas*?\?)")));
2992 g_variant_type_free (type);
2994 type = g_variant_format_string_scan_type ("mm(@xy^a&*?@?)", NULL, NULL);
2995 g_assert_null (type);
2999 do_failed_test (const char *test,
3000 const gchar *pattern)
3002 g_test_trap_subprocess (test, 1000000, G_TEST_SUBPROCESS_DEFAULT);
3003 g_test_trap_assert_failed ();
3004 g_test_trap_assert_stderr (pattern);
3008 test_invalid_varargs (void)
3013 if (!g_test_undefined ())
3016 g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
3017 "*GVariant format string*");
3018 g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
3019 "*valid_format_string*");
3020 value = g_variant_new ("z");
3021 g_test_assert_expected_messages ();
3022 g_assert_null (value);
3024 g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
3025 "*valid GVariant format string as a prefix*");
3026 g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
3027 "*valid_format_string*");
3028 value = g_variant_new_va ("z", &end, NULL);
3029 g_test_assert_expected_messages ();
3030 g_assert_null (value);
3032 value = g_variant_new ("y", 'a');
3033 g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
3034 "*type of 'q' but * has a type of 'y'*");
3035 g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
3036 "*valid_format_string*");
3037 g_variant_get (value, "q");
3038 g_test_assert_expected_messages ();
3039 g_variant_unref (value);
3043 check_and_free (GVariant *value,
3046 gchar *valstr = g_variant_print (value, FALSE);
3047 g_assert_cmpstr (str, ==, valstr);
3048 g_variant_unref (value);
3053 test_varargs_empty_array (void)
3055 g_variant_new ("(a{s*})", NULL);
3057 g_assert_not_reached ();
3064 GVariantBuilder array;
3066 g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
3067 g_variant_builder_add_parsed (&array, "{'size', <(%i, %i)> }", 800, 600);
3068 g_variant_builder_add (&array, "{sv}", "title",
3069 g_variant_new_string ("Test case"));
3070 g_variant_builder_add_value (&array,
3071 g_variant_new_dict_entry (g_variant_new_string ("temperature"),
3072 g_variant_new_variant (
3073 g_variant_new_double (37.5))));
3074 check_and_free (g_variant_new ("(ma{sv}m(a{sv})ma{sv}ii)",
3075 NULL, FALSE, NULL, &array, 7777, 8888),
3076 "(nothing, nothing, {'size': <(800, 600)>, "
3077 "'title': <'Test case'>, "
3078 "'temperature': <37.5>}, "
3081 check_and_free (g_variant_new ("(imimimmimmimmi)",
3088 "(123, nothing, 123, nothing, just nothing, 123)");
3090 check_and_free (g_variant_new ("(ybnixd)",
3091 'a', 1, 22, 33, (guint64) 44, 5.5),
3092 "(0x61, true, 22, 33, 44, 5.5)");
3094 check_and_free (g_variant_new ("(@y?*rv)",
3095 g_variant_new ("y", 'a'),
3096 g_variant_new ("y", 'b'),
3097 g_variant_new ("y", 'c'),
3098 g_variant_new ("(y)", 'd'),
3099 g_variant_new ("y", 'e')),
3100 "(0x61, 0x62, 0x63, (0x64,), <byte 0x65>)");
3104 GVariantBuilder array;
3112 g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
3113 for (i = 0; i < 100; i++)
3115 number = g_strdup_printf ("%u", i);
3116 g_variant_builder_add (&array, "s", number);
3120 value = g_variant_builder_end (&array);
3121 g_variant_iter_init (&iter, value);
3124 while (g_variant_iter_loop (&iter, "s", &number))
3126 gchar *check = g_strdup_printf ("%u", i++);
3127 g_assert_cmpstr (number, ==, check);
3130 g_assert_null (number);
3131 g_assert_cmpuint (i, ==, 100);
3133 g_variant_unref (value);
3135 g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
3136 for (i = 0; i < 100; i++)
3137 g_variant_builder_add (&array, "mi", i % 2 == 0, i);
3138 value = g_variant_builder_end (&array);
3141 g_variant_iter_init (&iter, value);
3142 while (g_variant_iter_loop (&iter, "mi", NULL, &val))
3143 g_assert_true (val == (gint) i++ || val == 0);
3144 g_assert_cmpuint (i, ==, 100);
3147 g_variant_iter_init (&iter, value);
3148 while (g_variant_iter_loop (&iter, "mi", &just, &val))
3154 g_assert_true (just);
3155 g_assert_cmpint (val, ==, this);
3159 g_assert_false (just);
3160 g_assert_cmpint (val, ==, 0);
3163 g_assert_cmpuint (i, ==, 100);
3165 g_variant_unref (value);
3169 const gchar *strvector[] = {"/hello", "/world", NULL};
3170 const gchar *test_strs[] = {"/foo", "/bar", "/baz" };
3171 GVariantBuilder builder;
3172 GVariantIter *array;
3180 g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
3181 g_variant_builder_add (&builder, "s", test_strs[0]);
3182 g_variant_builder_add (&builder, "s", test_strs[1]);
3183 g_variant_builder_add (&builder, "s", test_strs[2]);
3184 value = g_variant_new ("(as^as^a&s)", &builder, strvector, strvector);
3185 g_variant_iter_init (&tuple, value);
3186 g_variant_iter_next (&tuple, "as", &array);
3189 while (g_variant_iter_loop (array, "s", &str))
3190 g_assert_cmpstr (str, ==, test_strs[i++]);
3191 g_assert_cmpuint (i, ==, 3);
3193 g_variant_iter_free (array);
3196 g_variant_iter_init (&tuple, value);
3197 g_variant_iter_next (&tuple, "as", &array);
3200 while (g_variant_iter_loop (array, "&s", &str))
3201 g_assert_cmpstr (str, ==, test_strs[i++]);
3202 g_assert_cmpuint (i, ==, 3);
3204 g_variant_iter_free (array);
3206 g_variant_iter_next (&tuple, "^a&s", &strv);
3207 g_variant_iter_next (&tuple, "^as", &my_strv);
3209 g_assert_cmpstrv (strv, strvector);
3210 g_assert_cmpstrv (my_strv, strvector);
3212 g_variant_unref (value);
3213 g_strfreev (my_strv);
3218 const gchar *strvector[] = {"/hello", "/world", NULL};
3219 const gchar *test_strs[] = {"/foo", "/bar", "/baz" };
3220 GVariantBuilder builder;
3221 GVariantIter *array;
3229 g_variant_builder_init (&builder, G_VARIANT_TYPE ("aaay"));
3230 g_variant_builder_add (&builder, "^aay", strvector);
3231 g_variant_builder_add (&builder, "^aay", strvector);
3232 g_variant_builder_add (&builder, "^aay", strvector);
3233 value = g_variant_new ("aaay", &builder);
3234 array = g_variant_iter_new (value);
3236 while (g_variant_iter_loop (array, "^aay", &my_strv))
3238 g_assert_cmpuint (i, ==, 3);
3241 g_variant_iter_init (array, value);
3243 while (g_variant_iter_loop (array, "^a&ay", &strv))
3245 g_assert_cmpuint (i, ==, 3);
3246 g_variant_unref (value);
3247 g_variant_iter_free (array);
3250 g_variant_builder_init (&builder, G_VARIANT_TYPE ("aay"));
3251 g_variant_builder_add (&builder, "^ay", test_strs[0]);
3252 g_variant_builder_add (&builder, "^ay", test_strs[1]);
3253 g_variant_builder_add (&builder, "^ay", test_strs[2]);
3254 value = g_variant_new ("(aay^aay^a&ay)", &builder, strvector, strvector);
3255 g_variant_iter_init (&tuple, value);
3256 g_variant_iter_next (&tuple, "aay", &array);
3259 while (g_variant_iter_loop (array, "^ay", &str))
3260 g_assert_cmpstr (str, ==, test_strs[i++]);
3261 g_assert_cmpuint (i, ==, 3);
3263 g_variant_iter_free (array);
3266 g_variant_iter_init (&tuple, value);
3267 g_variant_iter_next (&tuple, "aay", &array);
3270 while (g_variant_iter_loop (array, "^&ay", &str))
3271 g_assert_cmpstr (str, ==, test_strs[i++]);
3272 g_assert_cmpuint (i, ==, 3);
3274 g_variant_iter_free (array);
3276 g_variant_iter_next (&tuple, "^a&ay", &strv);
3277 g_variant_iter_next (&tuple, "^aay", &my_strv);
3279 g_assert_cmpstrv (strv, strvector);
3280 g_assert_cmpstrv (my_strv, strvector);
3282 g_variant_unref (value);
3283 g_strfreev (my_strv);
3288 const gchar *strvector[] = {"/hello", "/world", NULL};
3289 const gchar *test_strs[] = {"/foo", "/bar", "/baz" };
3290 GVariantBuilder builder;
3291 GVariantIter *array;
3299 g_variant_builder_init (&builder, G_VARIANT_TYPE_OBJECT_PATH_ARRAY);
3300 g_variant_builder_add (&builder, "o", test_strs[0]);
3301 g_variant_builder_add (&builder, "o", test_strs[1]);
3302 g_variant_builder_add (&builder, "o", test_strs[2]);
3303 value = g_variant_new ("(ao^ao^a&o)", &builder, strvector, strvector);
3304 g_variant_iter_init (&tuple, value);
3305 g_variant_iter_next (&tuple, "ao", &array);
3308 while (g_variant_iter_loop (array, "o", &str))
3309 g_assert_cmpstr (str, ==, test_strs[i++]);
3310 g_assert_cmpuint (i, ==, 3);
3312 g_variant_iter_free (array);
3315 g_variant_iter_init (&tuple, value);
3316 g_variant_iter_next (&tuple, "ao", &array);
3319 while (g_variant_iter_loop (array, "&o", &str))
3320 g_assert_cmpstr (str, ==, test_strs[i++]);
3321 g_assert_cmpuint (i, ==, 3);
3323 g_variant_iter_free (array);
3325 g_variant_iter_next (&tuple, "^a&o", &strv);
3326 g_variant_iter_next (&tuple, "^ao", &my_strv);
3328 g_assert_cmpstrv (strv, strvector);
3329 g_assert_cmpstrv (my_strv, strvector);
3331 g_variant_unref (value);
3332 g_strfreev (my_strv);
3337 const gchar *strvector[] = { "i", "ii", "iii", "iv", "v", "vi", NULL };
3338 GVariantBuilder builder;
3347 g_variant_builder_init (&builder, G_VARIANT_TYPE ("aas"));
3348 g_variant_builder_open (&builder, G_VARIANT_TYPE ("as"));
3349 for (i = 0; i < 6; i++)
3351 g_variant_builder_add (&builder, "s", strvector[i]);
3353 g_variant_builder_add (&builder, "&s", strvector[i]);
3354 g_variant_builder_close (&builder);
3355 g_variant_builder_add (&builder, "^as", strvector);
3356 g_variant_builder_add (&builder, "^as", strvector);
3357 value = g_variant_new ("aas", &builder);
3359 g_variant_iter_init (&iter, value);
3360 while (g_variant_iter_loop (&iter, "^as", &strv))
3361 for (i = 0; i < 6; i++)
3362 g_assert_cmpstr (strv[i], ==, strvector[i]);
3364 g_variant_iter_init (&iter, value);
3365 while (g_variant_iter_loop (&iter, "^a&s", &strv))
3366 for (i = 0; i < 6; i++)
3367 g_assert_cmpstr (strv[i], ==, strvector[i]);
3369 g_variant_iter_init (&iter, value);
3370 while (g_variant_iter_loop (&iter, "as", &i2))
3375 while (g_variant_iter_loop (i2, "s", &str))
3376 g_assert_cmpstr (str, ==, strvector[i++]);
3377 g_assert_cmpuint (i, ==, 6);
3380 g_variant_iter_init (&iter, value);
3381 i3 = g_variant_iter_copy (&iter);
3382 while (g_variant_iter_loop (&iter, "@as", &sub))
3384 gchar *str = g_variant_print (sub, TRUE);
3385 g_assert_cmpstr (str, ==,
3386 "['i', 'ii', 'iii', 'iv', 'v', 'vi']");
3390 g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
3391 "*NULL has already been returned*");
3392 g_variant_iter_next_value (&iter);
3393 g_test_assert_expected_messages ();
3395 while (g_variant_iter_loop (i3, "*", &sub))
3397 gchar *str = g_variant_print (sub, TRUE);
3398 g_assert_cmpstr (str, ==,
3399 "['i', 'ii', 'iii', 'iv', 'v', 'vi']");
3403 g_variant_iter_free (i3);
3405 for (i = 0; i < g_variant_n_children (value); i++)
3409 g_variant_get_child (value, i, "*", &sub);
3411 for (j = 0; j < g_variant_n_children (sub); j++)
3413 const gchar *str = NULL;
3416 g_variant_get_child (sub, j, "&s", &str);
3417 g_assert_cmpstr (str, ==, strvector[j]);
3419 cval = g_variant_get_child_value (sub, j);
3420 g_variant_get (cval, "&s", &str);
3421 g_assert_cmpstr (str, ==, strvector[j]);
3422 g_variant_unref (cval);
3425 g_variant_unref (sub);
3428 g_variant_unref (value);
3447 /* test all 'nothing' */
3448 value = g_variant_new ("(mymbmnmqmimumxmtmhmdmv)",
3451 FALSE, (gint16) 123,
3452 FALSE, (guint16) 123,
3453 FALSE, (gint32) 123,
3454 FALSE, (guint32) 123,
3455 FALSE, (gint64) 123,
3456 FALSE, (guint64) 123,
3458 FALSE, (gdouble) 37.5,
3462 g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3476 memset (justs, 1, sizeof justs);
3477 g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3489 g_assert_true (!(justs[0] || justs[1] || justs[2] || justs[3] || justs[4] ||
3490 justs[5] || justs[6] || justs[7] || justs[8] || justs[9]));
3493 memset (justs, 1, sizeof justs);
3494 byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3498 g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3499 &justs[0], &byteval,
3510 g_assert_true (!(justs[0] || justs[1] || justs[2] || justs[3] || justs[4] ||
3511 justs[5] || justs[6] || justs[7] || justs[8] || justs[9]));
3512 g_assert_true (byteval == '\0' && bval == FALSE);
3513 g_assert_true (i16val == 0 && u16val == 0 && i32val == 0 &&
3514 u32val == 0 && i64val == 0 && u64val == 0 &&
3515 hval == 0 && dval == 0.0);
3516 g_assert_null (vval);
3519 byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3523 g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3535 g_assert_true (byteval == '\0' && bval == FALSE);
3536 g_assert_true (i16val == 0 && u16val == 0 && i32val == 0 &&
3537 u32val == 0 && i64val == 0 && u64val == 0 &&
3538 hval == 0 && dval == 0.0);
3539 g_assert_null (vval);
3541 g_variant_unref (value);
3544 /* test all 'just' */
3545 value = g_variant_new ("(mymbmnmqmimumxmtmhmdmv)",
3549 TRUE, (guint16) 123,
3551 TRUE, (guint32) 123,
3553 TRUE, (guint64) 123,
3555 TRUE, (gdouble) 37.5,
3556 g_variant_new ("()"));
3559 g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3573 memset (justs, 0, sizeof justs);
3574 g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3586 g_assert_true (justs[0] && justs[1] && justs[2] && justs[3] && justs[4] &&
3587 justs[5] && justs[6] && justs[7] && justs[8] && justs[9]);
3590 memset (justs, 0, sizeof justs);
3591 byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3595 g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3596 &justs[0], &byteval,
3607 g_assert_true (justs[0] && justs[1] && justs[2] && justs[3] && justs[4] &&
3608 justs[5] && justs[6] && justs[7] && justs[8] && justs[9]);
3609 g_assert_true (byteval == 'a' && bval == TRUE);
3610 g_assert_true (i16val == 123 && u16val == 123 && i32val == 123 &&
3611 u32val == 123 && i64val == 123 && u64val == 123 &&
3612 hval == -1 && dval == 37.5);
3613 g_assert_true (g_variant_is_of_type (vval, G_VARIANT_TYPE_UNIT));
3614 g_variant_unref (vval);
3617 byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3621 g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3633 g_assert_true (byteval == 'a' && bval == TRUE);
3634 g_assert_true (i16val == 123 && u16val == 123 && i32val == 123 &&
3635 u32val == 123 && i64val == 123 && u64val == 123 &&
3636 hval == -1 && dval == 37.5);
3637 g_assert_true (g_variant_is_of_type (vval, G_VARIANT_TYPE_UNIT));
3638 g_variant_unref (vval);
3640 g_variant_unref (value);
3647 value = g_variant_new ("(masas)", NULL, NULL);
3648 g_variant_ref_sink (value);
3650 str = g_variant_print (value, TRUE);
3651 g_assert_cmpstr (str, ==, "(@mas nothing, @as [])");
3652 g_variant_unref (value);
3655 do_failed_test ("/gvariant/varargs/subprocess/empty-array",
3656 "*which type of empty array*");
3659 g_variant_type_info_assert_no_infos ();
3663 hash_get (GVariant *value,
3664 const gchar *format,
3667 const gchar *endptr = NULL;
3671 hash = g_str_has_suffix (format, "#");
3673 va_start (ap, format);
3674 g_variant_get_va (value, format, hash ? &endptr : NULL, &ap);
3678 g_assert_cmpint (*endptr, ==, '#');
3682 hash_new (const gchar *format,
3685 const gchar *endptr = NULL;
3690 hash = g_str_has_suffix (format, "#");
3692 va_start (ap, format);
3693 value = g_variant_new_va (format, hash ? &endptr : NULL, &ap);
3697 g_assert_cmpint (*endptr, ==, '#');
3709 value = hash_new ("i", 234);
3710 hash_get (value, "i", &x);
3711 g_assert_cmpint (x, ==, 234);
3712 g_variant_unref (value);
3715 value = hash_new ("i#", 234);
3716 hash_get (value, "i#", &x);
3717 g_assert_cmpint (x, ==, 234);
3718 g_variant_unref (value);
3720 g_variant_type_info_assert_no_infos ();
3724 test_builder_memory (void)
3726 GVariantBuilder *hb;
3729 hb = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
3730 g_variant_builder_open (hb, G_VARIANT_TYPE_ARRAY);
3731 g_variant_builder_open (hb, G_VARIANT_TYPE_ARRAY);
3732 g_variant_builder_open (hb, G_VARIANT_TYPE_ARRAY);
3733 g_variant_builder_add (hb, "s", "some value");
3734 g_variant_builder_ref (hb);
3735 g_variant_builder_unref (hb);
3736 g_variant_builder_unref (hb);
3738 hb = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
3739 g_variant_builder_unref (hb);
3741 hb = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
3742 g_variant_builder_clear (hb);
3743 g_variant_builder_unref (hb);
3745 g_variant_builder_init (&sb, G_VARIANT_TYPE_ARRAY);
3746 g_variant_builder_open (&sb, G_VARIANT_TYPE_ARRAY);
3747 g_variant_builder_open (&sb, G_VARIANT_TYPE_ARRAY);
3748 g_variant_builder_add (&sb, "s", "some value");
3749 g_variant_builder_clear (&sb);
3751 g_variant_type_info_assert_no_infos ();
3757 GVariant *items[4096];
3761 table = g_hash_table_new_full (g_variant_hash, g_variant_equal,
3762 (GDestroyNotify ) g_variant_unref,
3765 for (i = 0; i < G_N_ELEMENTS (items); i++)
3771 tree = tree_instance_new (NULL, 0);
3772 items[i] = tree_instance_get_gvariant (tree);
3773 tree_instance_free (tree);
3775 for (j = 0; j < i; j++)
3776 if (g_variant_equal (items[i], items[j]))
3778 g_variant_unref (items[i]);
3782 g_hash_table_insert (table,
3783 g_variant_ref_sink (items[i]),
3784 GINT_TO_POINTER (i));
3787 for (i = 0; i < G_N_ELEMENTS (items); i++)
3791 result = g_hash_table_lookup (table, items[i]);
3792 g_assert_cmpint (GPOINTER_TO_INT (result), ==, i);
3795 g_hash_table_unref (table);
3797 g_variant_type_info_assert_no_infos ();
3801 test_gv_byteswap (void)
3803 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
3804 # define native16(x) x, 0
3805 # define swapped16(x) 0, x
3807 # define native16(x) 0, x
3808 # define swapped16(x) x, 0
3810 /* all kinds of crazy randomised testing already performed on the
3811 * byteswapper in the /gvariant/serializer/byteswap test and all kinds
3812 * of crazy randomised testing performed against the serializer
3813 * normalisation functions in the /gvariant/serializer/fuzz/ tests.
3815 * just test a few simple cases here to make sure they each work
3817 guchar validbytes[] = { 'a', '\0', swapped16(66), 2,
3819 'b', '\0', swapped16(77), 2,
3821 guchar corruptbytes[] = { 'a', '\0', swapped16(66), 2,
3823 'b', '\0', swapped16(77), 2,
3825 guint valid_data[4], corrupt_data[4];
3826 GVariant *value, *swapped;
3827 gchar *string, *string2;
3829 memcpy (valid_data, validbytes, sizeof validbytes);
3830 memcpy (corrupt_data, corruptbytes, sizeof corruptbytes);
3833 value = g_variant_new_from_data (G_VARIANT_TYPE ("a(sn)"),
3834 valid_data, sizeof validbytes, TRUE,
3836 swapped = g_variant_byteswap (value);
3837 g_variant_unref (value);
3838 g_assert_cmpuint (g_variant_get_size (swapped), ==, 13);
3839 string = g_variant_print (swapped, FALSE);
3840 g_variant_unref (swapped);
3841 g_assert_cmpstr (string, ==, "[('a', 66), ('b', 77)]");
3844 /* untrusted but valid */
3845 value = g_variant_new_from_data (G_VARIANT_TYPE ("a(sn)"),
3846 valid_data, sizeof validbytes, FALSE,
3848 swapped = g_variant_byteswap (value);
3849 g_variant_unref (value);
3850 g_assert_cmpuint (g_variant_get_size (swapped), ==, 13);
3851 string = g_variant_print (swapped, FALSE);
3852 g_variant_unref (swapped);
3853 g_assert_cmpstr (string, ==, "[('a', 66), ('b', 77)]");
3856 /* untrusted, invalid */
3857 value = g_variant_new_from_data (G_VARIANT_TYPE ("a(sn)"),
3858 corrupt_data, sizeof corruptbytes, FALSE,
3860 string = g_variant_print (value, FALSE);
3861 swapped = g_variant_byteswap (value);
3862 g_variant_unref (value);
3863 g_assert_cmpuint (g_variant_get_size (swapped), ==, 13);
3864 value = g_variant_byteswap (swapped);
3865 g_variant_unref (swapped);
3866 string2 = g_variant_print (value, FALSE);
3867 g_assert_cmpuint (g_variant_get_size (value), ==, 13);
3868 g_variant_unref (value);
3869 g_assert_cmpstr (string, ==, string2);
3875 test_gv_byteswap_non_normal_non_aligned (void)
3877 const guint8 data[] = { 0x02 };
3879 GVariant *v_byteswapped = NULL;
3881 g_test_summary ("Test that calling g_variant_byteswap() on a variant which "
3882 "is in non-normal form and doesn’t need byteswapping returns "
3883 "the same variant in normal form.");
3885 v = g_variant_new_from_data (G_VARIANT_TYPE_BOOLEAN, data, sizeof (data), FALSE, NULL, NULL);
3886 g_assert_false (g_variant_is_normal_form (v));
3888 v_byteswapped = g_variant_byteswap (v);
3889 g_assert_true (g_variant_is_normal_form (v_byteswapped));
3891 g_assert_cmpvariant (v, v_byteswapped);
3893 g_variant_unref (v);
3894 g_variant_unref (v_byteswapped);
3906 tree = tree_instance_new (NULL, 3);
3907 value = tree_instance_get_gvariant (tree);
3908 tree_instance_free (tree);
3910 pt = g_variant_print (value, TRUE);
3911 p = g_variant_print (value, FALSE);
3913 parsed = g_variant_parse (NULL, pt, NULL, NULL, NULL);
3914 res = g_variant_print (parsed, FALSE);
3915 g_assert_cmpstr (p, ==, res);
3916 g_variant_unref (parsed);
3919 parsed = g_variant_parse (g_variant_get_type (value), p,
3921 res = g_variant_print (parsed, TRUE);
3922 g_assert_cmpstr (pt, ==, res);
3923 g_variant_unref (parsed);
3926 g_variant_unref (value);
3936 for (i = 0; i < 100; i++)
3943 GError *error = NULL;
3948 for (i = 0; i < 127; i++)
3952 val = g_variant_new_string (str);
3953 p = g_variant_print (val, FALSE);
3954 g_variant_unref (val);
3956 val = g_variant_parse (NULL, p, NULL, NULL, &error);
3957 p2 = g_variant_print (val, FALSE);
3959 g_assert_cmpstr (str, ==, g_variant_get_string (val, NULL));
3960 g_assert_cmpstr (p, ==, p2);
3962 g_variant_unref (val);
3967 /* another mini test */
3972 value = g_variant_parse (G_VARIANT_TYPE_INT32, "1 2 3", NULL, &end, NULL);
3973 g_assert_cmpint (g_variant_get_int32 (value), ==, 1);
3974 /* make sure endptr returning works */
3975 g_assert_cmpstr (end, ==, " 2 3");
3976 g_variant_unref (value);
3979 /* unicode mini test */
3982 const gchar orig[] = "a\xc5\x82\xf0\x9d\x84\x9e \t\n";
3986 value = g_variant_new_string (orig);
3987 printed = g_variant_print (value, FALSE);
3988 g_variant_unref (value);
3990 g_assert_cmpstr (printed, ==, "'a\xc5\x82\xf0\x9d\x84\x9e \\t\\n'");
3991 value = g_variant_parse (NULL, printed, NULL, NULL, NULL);
3992 g_assert_cmpstr (g_variant_get_string (value, NULL), ==, orig);
3993 g_variant_unref (value);
3999 const gchar orig[] = " \342\200\254 \360\220\210\240 \a \b \f \n \r \t \v ";
4003 value = g_variant_new_string (orig);
4004 printed = g_variant_print (value, FALSE);
4005 g_variant_unref (value);
4007 g_assert_cmpstr (printed, ==, "' \\u202c \\U00010220 \\a \\b \\f \\n \\r \\t \\v '");
4008 value = g_variant_parse (NULL, printed, NULL, NULL, NULL);
4009 g_assert_cmpstr (g_variant_get_string (value, NULL), ==, orig);
4010 g_variant_unref (value);
4014 /* pattern coalese of `MN` and `*` is `MN` */
4016 GVariant *value = NULL;
4017 GError *error = NULL;
4019 value = g_variant_parse (NULL, "[[0], [], [nothing]]", NULL, NULL, &error);
4020 g_assert_no_error (error);
4021 g_assert_cmpstr (g_variant_get_type_string (value), ==, "aami");
4022 g_variant_unref (value);
4026 /* inf/nan strings are C99 features which Visual C++ does not support */
4027 /* inf/nan mini test */
4029 const gchar *tests[] = { "inf", "-inf", "nan" };
4032 gchar *printed_down;
4035 for (i = 0; i < G_N_ELEMENTS (tests); i++)
4037 GError *error = NULL;
4038 value = g_variant_parse (NULL, tests[i], NULL, NULL, &error);
4039 printed = g_variant_print (value, FALSE);
4040 /* Canonicalize to lowercase; https://bugzilla.gnome.org/show_bug.cgi?id=704585 */
4041 printed_down = g_ascii_strdown (printed, -1);
4042 g_assert_true (g_str_has_prefix (printed_down, tests[i]));
4044 g_free (printed_down);
4045 g_variant_unref (value);
4050 g_variant_type_info_assert_no_infos ();
4054 test_parse_failures (void)
4056 const gchar *test[] = {
4057 "[1, 2,", "6:", "expected value",
4058 "", "0:", "expected value",
4059 "(1, 2,", "6:", "expected value",
4060 "<1", "2:", "expected '>'",
4061 "[]", "0-2:", "unable to infer",
4062 "(,", "1:", "expected value",
4063 "[4,'']", "1-2,3-5:", "common type",
4064 "[4, '', 5]", "1-2,4-6:", "common type",
4065 "['', 4, 5]", "1-3,5-6:", "common type",
4066 "[4, 5, '']", "1-2,7-9:", "common type",
4067 "[[4], [], ['']]", "1-4,10-14:", "common type",
4068 "[[], [4], ['']]", "5-8,10-14:", "common type",
4069 "just", "4:", "expected value",
4070 "nothing", "0-7:", "unable to infer",
4071 "just [4, '']", "6-7,9-11:", "common type",
4072 "[[4,'']]", "2-3,4-6:", "common type",
4073 "([4,''],)", "2-3,4-6:", "common type",
4075 "{}", "0-2:", "unable to infer",
4076 "{[1,2],[3,4]}", "0-13:", "basic types",
4077 "{[1,2]:[3,4]}", "0-13:", "basic types",
4078 "justt", "0-5:", "unknown keyword",
4079 "nothng", "0-6:", "unknown keyword",
4080 "uint33", "0-6:", "unknown keyword",
4081 "@mi just ''", "9-11:", "can not parse as",
4082 "@ai ['']", "5-7:", "can not parse as",
4083 "@(i) ('',)", "6-8:", "can not parse as",
4084 "[[], 5]", "1-3,5-6:", "common type",
4085 "[[5], 5]", "1-4,6-7:", "common type",
4086 "5 5", "2:", "expected end of input",
4087 "[5, [5, '']]", "5-6,8-10:", "common type",
4088 "@i just 5", "3-9:", "can not parse as",
4089 "@i nothing", "3-10:", "can not parse as",
4090 "@i []", "3-5:", "can not parse as",
4091 "@i ()", "3-5:", "can not parse as",
4092 "@ai (4,)", "4-8:", "can not parse as",
4093 "@(i) []", "5-7:", "can not parse as",
4094 "(5 5)", "3:", "expected ','",
4095 "[5 5]", "3:", "expected ',' or ']'",
4096 "(5, 5 5)", "6:", "expected ',' or ')'",
4097 "[5, 5 5]", "6:", "expected ',' or ']'",
4098 "<@i []>", "4-6:", "can not parse as",
4099 "<[5 5]>", "4:", "expected ',' or ']'",
4100 "{[4,''],5}", "2-3,4-6:", "common type",
4101 "{5,[4,'']}", "4-5,6-8:", "common type",
4102 "@i {1,2}", "3-8:", "can not parse as",
4103 "{@i '', 5}", "4-6:", "can not parse as",
4104 "{5, @i ''}", "7-9:", "can not parse as",
4105 "@ai {}", "4-6:", "can not parse as",
4106 "{@i '': 5}", "4-6:", "can not parse as",
4107 "{5: @i ''}", "7-9:", "can not parse as",
4108 "{<4,5}", "3:", "expected '>'",
4109 "{4,<5}", "5:", "expected '>'",
4110 "{4,5,6}", "4:", "expected '}'",
4111 "{5 5}", "3:", "expected ':' or ','",
4112 "{4: 5: 6}", "5:", "expected ',' or '}'",
4113 "{4:5,<6:7}", "7:", "expected '>'",
4114 "{4:5,6:<7}", "9:", "expected '>'",
4115 "{4:5,6 7}", "7:", "expected ':'",
4116 "@o 'foo'", "3-8:", "object path",
4117 "@g 'zzz'", "3-8:", "signature",
4118 "@i true", "3-7:", "can not parse as",
4119 "@z 4", "0-2:", "invalid type",
4120 "@a* []", "0-3:", "definite",
4121 "@ai [3 3]", "7:", "expected ',' or ']'",
4122 "18446744073709551616", "0-20:", "too big for any type",
4123 "-18446744073709551616", "0-21:", "too big for any type",
4124 "byte 256", "5-8:", "out of range for type",
4125 "byte -1", "5-7:", "out of range for type",
4126 "int16 32768", "6-11:", "out of range for type",
4127 "int16 -32769", "6-12:", "out of range for type",
4128 "uint16 -1", "7-9:", "out of range for type",
4129 "uint16 65536", "7-12:", "out of range for type",
4130 "2147483648", "0-10:", "out of range for type",
4131 "-2147483649", "0-11:", "out of range for type",
4132 "uint32 -1", "7-9:", "out of range for type",
4133 "uint32 4294967296", "7-17:", "out of range for type",
4134 "@x 9223372036854775808", "3-22:", "out of range for type",
4135 "@x -9223372036854775809", "3-23:", "out of range for type",
4136 "@t -1", "3-5:", "out of range for type",
4137 "@t 18446744073709551616", "3-23:", "too big for any type",
4138 "handle 2147483648", "7-17:", "out of range for type",
4139 "handle -2147483649", "7-18:", "out of range for type",
4140 "1.798e308", "0-9:", "too big for any type",
4141 "37.5a488", "4-5:", "invalid character",
4142 "0x7ffgf", "5-6:", "invalid character",
4143 "07758", "4-5:", "invalid character",
4144 "123a5", "3-4:", "invalid character",
4145 "@ai 123", "4-7:", "can not parse as",
4146 "'\"\\'", "0-4:", "unterminated string",
4147 "'\"\\'\\", "0-5:", "unterminated string",
4148 "boolean 4", "8-9:", "can not parse as",
4149 "int32 true", "6-10:", "can not parse as",
4150 "[double 5, int32 5]", "1-9,11-18:", "common type",
4151 "string 4", "7-8:", "can not parse as",
4152 "\x0a", "1:", "expected value",
4153 "((", "2:", "expected value",
4154 "(b", "1:", "expected value",
4155 "b'", "0-2:", "unterminated string constant",
4156 "b\"", "0-2:", "unterminated string constant",
4157 "b'a", "0-3:", "unterminated string constant",
4158 "b\"a", "0-3:", "unterminated string constant",
4159 "b'\\", "0-3:", "unterminated string constant",
4160 "b\"\\", "0-3:", "unterminated string constant",
4161 "b'\\'", "0-4:", "unterminated string constant",
4162 "b\"\\\"", "0-4:", "unterminated string constant",
4163 "b'\\'a", "0-5:", "unterminated string constant",
4164 "b\"\\\"a", "0-5:", "unterminated string constant",
4165 "'\\u-ff4'", "3:", "invalid 4-character unicode escape",
4166 "'\\u+ff4'", "3:", "invalid 4-character unicode escape",
4167 "'\\u'", "3:", "invalid 4-character unicode escape",
4168 "'\\u0'", "3-4:", "invalid 4-character unicode escape",
4169 "'\\uHELLO'", "3:", "invalid 4-character unicode escape",
4170 "'\\u ff4'", "3:", "invalid 4-character unicode escape",
4171 "'\\u012'", "3-6:", "invalid 4-character unicode escape",
4172 "'\\u0xff4'", "3-4:", "invalid 4-character unicode escape",
4173 "'\\U-ff4'", "3:", "invalid 8-character unicode escape",
4174 "'\\U+ff4'", "3:", "invalid 8-character unicode escape",
4175 "'\\U'", "3:", "invalid 8-character unicode escape",
4176 "'\\U0'", "3-4:", "invalid 8-character unicode escape",
4177 "'\\UHELLO'", "3:", "invalid 8-character unicode escape",
4178 "'\\U ff4'", "3:", "invalid 8-character unicode escape",
4179 "'\\U0123456'", "3-10:", "invalid 8-character unicode escape",
4180 "'\\U0xff4'", "3-4:", "invalid 8-character unicode escape",
4184 for (i = 0; i < G_N_ELEMENTS (test); i += 3)
4186 GError *error1 = NULL, *error2 = NULL;
4189 /* Copy the test string and drop its nul terminator, then use the @limit
4190 * parameter of g_variant_parse() to set the length. This allows valgrind
4191 * to catch 1-byte heap buffer overflows. */
4192 gsize test_len = MAX (strlen (test[i]), 1);
4193 gchar *test_blob = g_malloc0 (test_len); /* no nul terminator */
4195 memcpy (test_blob, test[i], test_len);
4196 value = g_variant_parse (NULL, test_blob, test_blob + test_len, NULL, &error1);
4197 g_assert_null (value);
4201 if (!strstr (error1->message, test[i+2]))
4202 g_error ("test %u: Can't find '%s' in '%s'", i / 3,
4203 test[i+2], error1->message);
4205 if (!g_str_has_prefix (error1->message, test[i+1]))
4206 g_error ("test %u: Expected location '%s' in '%s'", i / 3,
4207 test[i+1], error1->message);
4209 /* Test again with the nul terminator this time. The behaviour should be
4211 value = g_variant_parse (NULL, test[i], NULL, NULL, &error2);
4212 g_assert_null (value);
4214 g_assert_cmpint (error1->domain, ==, error2->domain);
4215 g_assert_cmpint (error1->code, ==, error2->code);
4216 g_assert_cmpstr (error1->message, ==, error2->message);
4218 g_clear_error (&error1);
4219 g_clear_error (&error2);
4223 /* Test that parsing GVariant text format integers works at the boundaries of
4224 * those integer types. We’re especially interested in the handling of the most
4225 * negative numbers, since those can’t be represented in sign + absolute value
4228 test_parser_integer_bounds (void)
4230 GVariant *value = NULL;
4231 GError *local_error = NULL;
4233 #define test_bound(TYPE, type, text, expected_value) \
4234 value = g_variant_parse (G_VARIANT_TYPE_##TYPE, text, NULL, NULL, &local_error); \
4235 g_assert_no_error (local_error); \
4236 g_assert_nonnull (value); \
4237 g_assert_true (g_variant_is_of_type (value, G_VARIANT_TYPE_##TYPE)); \
4238 g_assert_cmpint (g_variant_get_##type (value), ==, expected_value); \
4239 g_variant_unref (value)
4241 test_bound (BYTE, byte, "0", 0);
4242 test_bound (BYTE, byte, "255", G_MAXUINT8);
4243 test_bound (INT16, int16, "-32768", G_MININT16);
4244 test_bound (INT16, int16, "32767", G_MAXINT16);
4245 test_bound (INT32, int32, "-2147483648", G_MININT32);
4246 test_bound (INT32, int32, "2147483647", G_MAXINT32);
4247 test_bound (INT64, int64, "-9223372036854775808", G_MININT64);
4248 test_bound (INT64, int64, "9223372036854775807", G_MAXINT64);
4249 test_bound (HANDLE, handle, "-2147483648", G_MININT32);
4250 test_bound (HANDLE, handle, "2147483647", G_MAXINT32);
4255 /* Test that #GVariants which recurse too deeply are rejected. */
4257 test_parser_recursion (void)
4259 GVariant *value = NULL;
4260 GError *local_error = NULL;
4261 const guint recursion_depth = G_VARIANT_MAX_RECURSION_DEPTH + 1;
4262 gchar *silly_dict = g_malloc0 (recursion_depth * 2 + 1);
4265 for (i = 0; i < recursion_depth; i++)
4267 silly_dict[i] = '{';
4268 silly_dict[recursion_depth * 2 - i - 1] = '}';
4271 value = g_variant_parse (NULL, silly_dict, NULL, NULL, &local_error);
4272 g_assert_error (local_error, G_VARIANT_PARSE_ERROR, G_VARIANT_PARSE_ERROR_RECURSION);
4273 g_assert_null (value);
4274 g_error_free (local_error);
4275 g_free (silly_dict);
4278 /* Test that #GVariants which recurse too deeply through use of typedecls are
4279 * rejected. This is a sneaky way to multiply the number of objects in a text
4280 * representation of a #GVariant without making the text-form proportionately
4281 * long. It uses a typedecl to nest one of the elements deeply within nested
4282 * maybes, while keeping all the other elements un-nested in the text form. It
4283 * relies on g_variant_parse() not being provided with a concrete type for the
4284 * top-level #GVariant. */
4286 test_parser_recursion_typedecls (void)
4288 GVariant *value = NULL;
4289 GError *local_error = NULL;
4290 const guint recursion_depth = G_VARIANT_MAX_RECURSION_DEPTH - 1;
4291 gchar *silly_type = g_malloc0 (recursion_depth + 2 /* trailing `u` and then nul */);
4292 gchar *silly_array = NULL;
4295 for (i = 0; i < recursion_depth; i++)
4296 silly_type[i] = 'm';
4297 silly_type[recursion_depth] = 'u';
4299 silly_array = g_strdup_printf ("[1,2,3,@%s 0]", silly_type);
4301 value = g_variant_parse (NULL, silly_array, NULL, NULL, &local_error);
4302 g_assert_error (local_error, G_VARIANT_PARSE_ERROR, G_VARIANT_PARSE_ERROR_RECURSION);
4303 g_assert_null (value);
4304 g_error_free (local_error);
4305 g_free (silly_array);
4306 g_free (silly_type);
4310 test_parser_recursion_maybes (void)
4312 const gchar *hello = "hello";
4315 const gchar *text_form; /* (not nullable) */
4316 GVariant *expected_variant; /* (not nullable) (owned) */
4321 /* fixed size base value */
4323 g_variant_ref_sink (g_variant_new_maybe (NULL, g_variant_new_maybe (NULL, g_variant_new_maybe (NULL, g_variant_new_uint32 (5)))))
4326 /* variable size base value */
4328 g_variant_ref_sink (g_variant_new_maybe (NULL, g_variant_new_maybe (NULL, g_variant_new_maybe (NULL, g_variant_new_strv (&hello, 1)))))
4331 /* fixed size base value, unset */
4332 "@mmmu just just nothing",
4333 g_variant_ref_sink (g_variant_new_maybe (NULL, g_variant_new_maybe (NULL, g_variant_new_maybe (G_VARIANT_TYPE_UINT32, NULL))))
4336 /* variable size base value, unset */
4337 "@mmmas just just nothing",
4338 g_variant_ref_sink (g_variant_new_maybe (NULL, g_variant_new_maybe (NULL, g_variant_new_maybe (G_VARIANT_TYPE_STRING_ARRAY, NULL))))
4341 /* fixed size base value, unset */
4342 "@mmmu just nothing",
4343 g_variant_ref_sink (g_variant_new_maybe (NULL, g_variant_new_maybe (G_VARIANT_TYPE ("mu"), NULL)))
4346 /* variable size base value, unset */
4347 "@mmmas just nothing",
4348 g_variant_ref_sink (g_variant_new_maybe (NULL, g_variant_new_maybe (G_VARIANT_TYPE ("mas"), NULL)))
4351 /* fixed size base value, unset */
4353 g_variant_ref_sink (g_variant_new_maybe (G_VARIANT_TYPE ("mmu"), NULL))
4356 /* variable size base value, unset */
4358 g_variant_ref_sink (g_variant_new_maybe (G_VARIANT_TYPE ("mmas"), NULL))
4363 g_test_summary ("Test that nested maybes are handled correctly when parsing text-form variants");
4364 g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2782");
4366 for (i = 0; i < G_N_ELEMENTS (vectors); i++)
4368 GVariant *value = NULL;
4369 GError *local_error = NULL;
4371 g_test_message ("Text form %" G_GSIZE_FORMAT ": %s", i, vectors[i].text_form);
4373 value = g_variant_parse (NULL, vectors[i].text_form, NULL, NULL, &local_error);
4374 g_assert_no_error (local_error);
4375 g_assert_nonnull (value);
4377 g_assert_cmpvariant (value, vectors[i].expected_variant);
4379 g_variant_unref (value);
4381 g_clear_pointer (&vectors[i].expected_variant, g_variant_unref);
4386 test_parse_bad_format_char (void)
4388 g_variant_new_parsed ("%z");
4390 g_assert_not_reached ();
4394 test_parse_bad_format_string (void)
4396 g_variant_new_parsed ("uint32 %i", 2);
4398 g_assert_not_reached ();
4402 test_parse_bad_args (void)
4404 g_variant_new_parsed ("%@i", g_variant_new_uint32 (2));
4406 g_assert_not_reached ();
4410 test_parse_positional (void)
4413 check_and_free (g_variant_new_parsed ("[('one', 1), (%s, 2),"
4414 " ('three', %i)]", "two", 3),
4415 "[('one', 1), ('two', 2), ('three', 3)]");
4416 value = g_variant_new_parsed ("[('one', 1), (%s, 2),"
4417 " ('three', %u)]", "two", 3);
4418 g_assert_true (g_variant_is_of_type (value, G_VARIANT_TYPE ("a(su)")));
4419 check_and_free (value, "[('one', 1), ('two', 2), ('three', 3)]");
4420 check_and_free (g_variant_new_parsed ("{%s:%i}", "one", 1), "{'one': 1}");
4422 if (g_test_undefined ())
4424 do_failed_test ("/gvariant/parse/subprocess/bad-format-char",
4425 "*GVariant format string*");
4427 do_failed_test ("/gvariant/parse/subprocess/bad-format-string",
4428 "*can not parse as*");
4430 do_failed_test ("/gvariant/parse/subprocess/bad-args",
4431 "*expected GVariant of type 'i'*");
4436 test_floating (void)
4440 value = g_variant_new_int32 (42);
4441 g_assert_true (g_variant_is_floating (value));
4442 g_variant_ref_sink (value);
4443 g_assert_true (!g_variant_is_floating (value));
4444 g_variant_unref (value);
4448 test_bytestring (void)
4450 const gchar *test_string = "foo,bar,baz,quux,\xffoooo";
4454 const gchar *const_str;
4455 GVariant *untrusted_empty;
4457 strv = g_strsplit (test_string, ",", 0);
4459 value = g_variant_new_bytestring_array ((const gchar **) strv, -1);
4460 g_assert_true (g_variant_is_floating (value));
4463 str = g_variant_print (value, FALSE);
4464 g_variant_unref (value);
4466 value = g_variant_parse (NULL, str, NULL, NULL, NULL);
4469 strv = g_variant_dup_bytestring_array (value, NULL);
4470 g_variant_unref (value);
4472 str = g_strjoinv (",", strv);
4475 g_assert_cmpstr (str, ==, test_string);
4478 strv = g_strsplit (test_string, ",", 0);
4479 value = g_variant_new ("(^aay^a&ay^ay^&ay)",
4480 strv, strv, strv[0], strv[0]);
4483 g_variant_get_child (value, 0, "^a&ay", &strv);
4484 str = g_strjoinv (",", strv);
4486 g_assert_cmpstr (str, ==, test_string);
4489 g_variant_get_child (value, 0, "^aay", &strv);
4490 str = g_strjoinv (",", strv);
4492 g_assert_cmpstr (str, ==, test_string);
4495 g_variant_get_child (value, 1, "^a&ay", &strv);
4496 str = g_strjoinv (",", strv);
4498 g_assert_cmpstr (str, ==, test_string);
4501 g_variant_get_child (value, 1, "^aay", &strv);
4502 str = g_strjoinv (",", strv);
4504 g_assert_cmpstr (str, ==, test_string);
4507 g_variant_get_child (value, 2, "^ay", &str);
4508 g_assert_cmpstr (str, ==, "foo");
4511 g_variant_get_child (value, 2, "^&ay", &str);
4512 g_assert_cmpstr (str, ==, "foo");
4514 g_variant_get_child (value, 3, "^ay", &str);
4515 g_assert_cmpstr (str, ==, "foo");
4518 g_variant_get_child (value, 3, "^&ay", &str);
4519 g_assert_cmpstr (str, ==, "foo");
4520 g_variant_unref (value);
4522 untrusted_empty = g_variant_new_from_data (G_VARIANT_TYPE ("ay"), NULL, 0, FALSE, NULL, NULL);
4523 value = g_variant_get_normal_form (untrusted_empty);
4524 const_str = g_variant_get_bytestring (value);
4526 g_variant_unref (value);
4527 g_variant_unref (untrusted_empty);
4531 test_lookup_value (void)
4534 const gchar *dict, *key, *value;
4536 { "@a{ss} {'x': 'y'}", "x", "'y'" },
4537 { "@a{ss} {'x': 'y'}", "y", NULL },
4538 { "@a{os} {'/x': 'y'}", "/x", "'y'" },
4539 { "@a{os} {'/x': 'y'}", "/y", NULL },
4540 { "@a{sv} {'x': <'y'>}", "x", "'y'" },
4541 { "@a{sv} {'x': <5>}", "x", "5" },
4542 { "@a{sv} {'x': <'y'>}", "y", NULL }
4546 for (i = 0; i < G_N_ELEMENTS (cases); i++)
4548 GVariant *dictionary;
4552 dictionary = g_variant_parse (NULL, cases[i].dict, NULL, NULL, NULL);
4553 value = g_variant_lookup_value (dictionary, cases[i].key, NULL);
4554 g_variant_unref (dictionary);
4556 if (value == NULL && cases[i].value == NULL)
4559 g_assert_true (value && cases[i].value);
4560 p = g_variant_print (value, FALSE);
4561 g_assert_cmpstr (cases[i].value, ==, p);
4562 g_variant_unref (value);
4575 dict = g_variant_parse (NULL,
4576 "{'a': <5>, 'b': <'c'>}",
4579 ok = g_variant_lookup (dict, "a", "i", &num);
4581 g_assert_cmpint (num, ==, 5);
4583 ok = g_variant_lookup (dict, "a", "&s", &str);
4584 g_assert_false (ok);
4586 ok = g_variant_lookup (dict, "q", "&s", &str);
4587 g_assert_false (ok);
4589 ok = g_variant_lookup (dict, "b", "i", &num);
4590 g_assert_false (ok);
4592 ok = g_variant_lookup (dict, "b", "&s", &str);
4594 g_assert_cmpstr (str, ==, "c");
4596 ok = g_variant_lookup (dict, "q", "&s", &str);
4597 g_assert_false (ok);
4599 g_variant_unref (dict);
4603 untrusted (GVariant *a)
4606 const GVariantType *type;
4609 type = g_variant_get_type (a);
4610 bytes = g_variant_get_data_as_bytes (a);
4611 b = g_variant_new_from_bytes (type, bytes, FALSE);
4612 g_bytes_unref (bytes);
4613 g_variant_unref (a);
4624 a = untrusted (g_variant_new_byte (5));
4625 b = g_variant_new_byte (6);
4626 g_assert_cmpint (g_variant_compare (a, b), <, 0);
4627 g_variant_unref (a);
4628 g_variant_unref (b);
4629 a = untrusted (g_variant_new_int16 (G_MININT16));
4630 b = g_variant_new_int16 (G_MAXINT16);
4631 g_assert_cmpint (g_variant_compare (a, b), <, 0);
4632 g_variant_unref (a);
4633 g_variant_unref (b);
4634 a = untrusted (g_variant_new_uint16 (0));
4635 b = g_variant_new_uint16 (G_MAXUINT16);
4636 g_assert_cmpint (g_variant_compare (a, b), <, 0);
4637 g_variant_unref (a);
4638 g_variant_unref (b);
4639 a = untrusted (g_variant_new_int32 (G_MININT32));
4640 b = g_variant_new_int32 (G_MAXINT32);
4641 g_assert_cmpint (g_variant_compare (a, b), <, 0);
4642 g_variant_unref (a);
4643 g_variant_unref (b);
4644 a = untrusted (g_variant_new_uint32 (0));
4645 b = g_variant_new_uint32 (G_MAXUINT32);
4646 g_assert_cmpint (g_variant_compare (a, b), <, 0);
4647 g_variant_unref (a);
4648 g_variant_unref (b);
4649 a = untrusted (g_variant_new_int64 (G_MININT64));
4650 b = g_variant_new_int64 (G_MAXINT64);
4651 g_assert_cmpint (g_variant_compare (a, b), <, 0);
4652 g_variant_unref (a);
4653 g_variant_unref (b);
4654 a = untrusted (g_variant_new_uint64 (0));
4655 b = g_variant_new_uint64 (G_MAXUINT64);
4656 g_assert_cmpint (g_variant_compare (a, b), <, 0);
4657 g_variant_unref (a);
4658 g_variant_unref (b);
4659 a = untrusted (g_variant_new_double (G_MINDOUBLE));
4660 b = g_variant_new_double (G_MAXDOUBLE);
4661 g_assert_cmpint (g_variant_compare (a, b), <, 0);
4662 g_variant_unref (a);
4663 g_variant_unref (b);
4664 a = untrusted (g_variant_new_string ("abc"));
4665 b = g_variant_new_string ("abd");
4666 g_assert_cmpint (g_variant_compare (a, b), <, 0);
4667 g_variant_unref (a);
4668 g_variant_unref (b);
4669 a = untrusted (g_variant_new_object_path ("/abc"));
4670 b = g_variant_new_object_path ("/abd");
4671 g_assert_cmpint (g_variant_compare (a, b), <, 0);
4672 g_variant_unref (a);
4673 g_variant_unref (b);
4674 a = untrusted (g_variant_new_signature ("g"));
4675 b = g_variant_new_signature ("o");
4676 g_assert_cmpint (g_variant_compare (a, b), <, 0);
4677 g_variant_unref (a);
4678 g_variant_unref (b);
4679 a = untrusted (g_variant_new_boolean (FALSE));
4680 b = g_variant_new_boolean (TRUE);
4681 g_assert_cmpint (g_variant_compare (a, b), <, 0);
4682 g_variant_unref (a);
4683 g_variant_unref (b);
4692 a = untrusted (g_variant_new_byte (5));
4693 b = g_variant_get_normal_form (a);
4694 g_assert_cmpvariant (a, b);
4695 g_variant_unref (a);
4696 g_variant_unref (b);
4697 a = untrusted (g_variant_new_int16 (G_MININT16));
4698 b = g_variant_get_normal_form (a);
4699 g_assert_cmpvariant (a, b);
4700 g_variant_unref (a);
4701 g_variant_unref (b);
4702 a = untrusted (g_variant_new_uint16 (0));
4703 b = g_variant_get_normal_form (a);
4704 g_assert_cmpvariant (a, b);
4705 g_variant_unref (a);
4706 g_variant_unref (b);
4707 a = untrusted (g_variant_new_int32 (G_MININT32));
4708 b = g_variant_get_normal_form (a);
4709 g_assert_cmpvariant (a, b);
4710 g_variant_unref (a);
4711 g_variant_unref (b);
4712 a = untrusted (g_variant_new_uint32 (0));
4713 b = g_variant_get_normal_form (a);
4714 g_assert_cmpvariant (a, b);
4715 g_variant_unref (a);
4716 g_variant_unref (b);
4717 a = untrusted (g_variant_new_int64 (G_MININT64));
4718 b = g_variant_get_normal_form (a);
4719 g_assert_cmpvariant (a, b);
4720 g_variant_unref (a);
4721 g_variant_unref (b);
4722 a = untrusted (g_variant_new_uint64 (0));
4723 b = g_variant_get_normal_form (a);
4724 g_assert_cmpvariant (a, b);
4725 g_variant_unref (a);
4726 g_variant_unref (b);
4727 a = untrusted (g_variant_new_double (G_MINDOUBLE));
4728 b = g_variant_get_normal_form (a);
4729 g_assert_cmpvariant (a, b);
4730 g_variant_unref (a);
4731 g_variant_unref (b);
4732 a = untrusted (g_variant_new_string ("abc"));
4733 g_assert_cmpvariant (a, a);
4734 b = g_variant_get_normal_form (a);
4735 g_assert_cmpvariant (a, b);
4736 g_variant_unref (a);
4737 g_variant_unref (b);
4738 a = untrusted (g_variant_new_object_path ("/abc"));
4739 g_assert_cmpvariant (a, a);
4740 b = g_variant_get_normal_form (a);
4742 g_assert_cmpvariant (a, b);
4743 g_variant_unref (a);
4744 g_variant_unref (b);
4745 a = untrusted (g_variant_new_signature ("g"));
4746 g_assert_cmpvariant (a, a);
4747 b = g_variant_get_normal_form (a);
4749 g_assert_cmpvariant (a, b);
4750 g_variant_unref (a);
4751 g_variant_unref (b);
4752 a = untrusted (g_variant_new_boolean (FALSE));
4753 b = g_variant_get_normal_form (a);
4754 g_assert_cmpvariant (a, b);
4755 g_variant_unref (a);
4756 g_variant_unref (b);
4760 test_fixed_array (void)
4769 a = g_variant_new_parsed ("[1,2,3,4,5]");
4770 elts = g_variant_get_fixed_array (a, &n_elts, sizeof (gint32));
4771 g_assert_cmpuint (n_elts, ==, 5);
4772 for (i = 0; i < 5; i++)
4773 g_assert_cmpint (elts[i], ==, i + 1);
4774 g_variant_unref (a);
4777 for (i = 0; i < 5; i++)
4779 a = g_variant_new_fixed_array (G_VARIANT_TYPE_INT32, values,
4780 G_N_ELEMENTS (values), sizeof (values[0]));
4781 g_assert_cmpstr (g_variant_get_type_string (a), ==, "ai");
4782 elts = g_variant_get_fixed_array (a, &n_elts, sizeof (gint32));
4783 g_assert_cmpuint (n_elts, ==, 5);
4784 for (i = 0; i < 5; i++)
4785 g_assert_cmpint (elts[i], ==, i + 1);
4786 g_variant_unref (a);
4790 test_check_format_string (void)
4794 value = g_variant_new ("(sas)", "foo", NULL);
4795 g_variant_ref_sink (value);
4797 g_assert_true (g_variant_check_format_string (value, "(s*)", TRUE));
4798 g_assert_true (g_variant_check_format_string (value, "(s*)", FALSE));
4799 g_assert_false (g_variant_check_format_string (value, "(u*)", TRUE));
4800 g_assert_false (g_variant_check_format_string (value, "(u*)", FALSE));
4802 g_assert_true (g_variant_check_format_string (value, "(&s*)", FALSE));
4803 g_test_expect_message ("GLib", G_LOG_LEVEL_CRITICAL, "*contains a '&' character*");
4804 g_assert_false (g_variant_check_format_string (value, "(&s*)", TRUE));
4805 g_test_assert_expected_messages ();
4807 g_assert_true (g_variant_check_format_string (value, "(s^as)", TRUE));
4808 g_assert_true (g_variant_check_format_string (value, "(s^as)", FALSE));
4810 g_test_expect_message ("GLib", G_LOG_LEVEL_CRITICAL, "*contains a '&' character*");
4811 g_assert_false (g_variant_check_format_string (value, "(s^a&s)", TRUE));
4812 g_test_assert_expected_messages ();
4813 g_assert_true (g_variant_check_format_string (value, "(s^a&s)", FALSE));
4815 g_variant_unref (value);
4817 /* Do it again with a type that will let us put a '&' after a '^' */
4818 value = g_variant_new ("(say)", "foo", NULL);
4819 g_variant_ref_sink (value);
4821 g_assert_true (g_variant_check_format_string (value, "(s*)", TRUE));
4822 g_assert_true (g_variant_check_format_string (value, "(s*)", FALSE));
4823 g_assert_false (g_variant_check_format_string (value, "(u*)", TRUE));
4824 g_assert_false (g_variant_check_format_string (value, "(u*)", FALSE));
4826 g_assert_true (g_variant_check_format_string (value, "(&s*)", FALSE));
4827 g_test_expect_message ("GLib", G_LOG_LEVEL_CRITICAL, "*contains a '&' character*");
4828 g_assert_false (g_variant_check_format_string (value, "(&s*)", TRUE));
4829 g_test_assert_expected_messages ();
4831 g_assert_true (g_variant_check_format_string (value, "(s^ay)", TRUE));
4832 g_assert_true (g_variant_check_format_string (value, "(s^ay)", FALSE));
4834 g_test_expect_message ("GLib", G_LOG_LEVEL_CRITICAL, "*contains a '&' character*");
4835 g_assert_false (g_variant_check_format_string (value, "(s^&ay)", TRUE));
4836 g_test_assert_expected_messages ();
4837 g_assert_true (g_variant_check_format_string (value, "(s^&ay)", FALSE));
4839 g_assert_true (g_variant_check_format_string (value, "r", FALSE));
4840 g_assert_true (g_variant_check_format_string (value, "(?a?)", FALSE));
4842 g_variant_unref (value);
4846 verify_gvariant_checksum (const gchar *sha256,
4851 checksum = g_compute_checksum_for_data (G_CHECKSUM_SHA256,
4852 g_variant_get_data (v),
4853 g_variant_get_size (v));
4854 g_assert_cmpstr (sha256, ==, checksum);
4859 verify_gvariant_checksum_va (const gchar *sha256,
4866 va_start (args, fmt);
4868 v = g_variant_new_va (fmt, NULL, &args);
4869 g_variant_ref_sink (v);
4870 #if G_BYTE_ORDER == G_BIG_ENDIAN
4872 GVariant *byteswapped = g_variant_byteswap (v);
4873 g_variant_unref (v);
4880 verify_gvariant_checksum (sha256, v);
4882 g_variant_unref (v);
4886 test_checksum_basic (void)
4888 verify_gvariant_checksum_va ("e8a4b2ee7ede79a3afb332b5b6cc3d952a65fd8cffb897f5d18016577c33d7cc",
4890 verify_gvariant_checksum_va ("c53e363c33b00cfce298229ee83856b8a98c2e6126cab13f65899f62473b0df5",
4892 verify_gvariant_checksum_va ("2b4c342f5433ebe591a1da77e013d1b72475562d48578dca8b84bac6651c3cb9",
4894 verify_gvariant_checksum_va ("12a3ae445661ce5dee78d0650d33362dec29c4f82af05e7e57fb595bbbacf0ca",
4896 verify_gvariant_checksum_va ("e25a59b24440eb6c833aa79c93b9840e6eab6966add0dacf31df7e9e7000f5b3",
4898 verify_gvariant_checksum_va ("4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a",
4900 verify_gvariant_checksum_va ("ca2fd00fa001190744c15c317643ab092e7048ce086a243e2be9437c898de1bb",
4905 test_checksum_nested (void)
4907 static const char* const strv[] = {"foo", "bar", "baz", NULL};
4909 verify_gvariant_checksum_va ("31fbc92f08fddaca716188fe4b5d44ae122fc6306fd3c6925af53cfa47ea596d",
4911 verify_gvariant_checksum_va ("01759d683cead856d1d386d59af0578841698a424a265345ad5413122f220de8",
4912 "(su)", "moocow", 79);
4913 verify_gvariant_checksum_va ("52b3ae95f19b3e642ea1d01185aea14a09004c1d1712672644427403a8a0afe6",
4914 "(qyst)", G_MAXUINT16, 9, "moocow", G_MAXUINT64);
4915 verify_gvariant_checksum_va ("6fc6f4524161c3ae0d316812d7088e3fcd372023edaea2d7821093be40ae1060",
4916 "(@ay)", g_variant_new_bytestring ("\xFF\xFF\xFF"));
4917 verify_gvariant_checksum_va ("572aca386e1a983dd23bb6eb6e3dfa72eef9ca7c7744581aa800e18d7d9d0b0b",
4919 verify_gvariant_checksum_va ("4bddf6174c791bb44fc6a4106573031690064df34b741033a0122ed8dc05bcf3",
4920 "(yvu)", 254, g_variant_new ("(^as)", strv), 42);
4930 const guint8 values[5] = { 1, 2, 3, 4, 5 };
4935 bytes = g_bytes_new (&values, 5);
4936 a = g_variant_new_from_bytes (G_VARIANT_TYPE_BYTESTRING, bytes, TRUE);
4937 g_bytes_unref (bytes);
4939 elts = g_variant_get_fixed_array (a, &n_elts, sizeof (guint8));
4940 g_assert_cmpuint (n_elts, ==, 5);
4941 for (i = 0; i < 5; i++)
4942 g_assert_cmpuint (elts[i], ==, i + 1);
4944 bytes2 = g_variant_get_data_as_bytes (a);
4945 g_variant_unref (a);
4947 bytes = g_bytes_new (&values, 5);
4948 g_assert_true (g_bytes_equal (bytes, bytes2));
4949 g_bytes_unref (bytes);
4950 g_bytes_unref (bytes2);
4952 tuple = g_variant_new_parsed ("['foo', 'bar']");
4953 bytes = g_variant_get_data_as_bytes (tuple); /* force serialization */
4954 a = g_variant_get_child_value (tuple, 1);
4955 bytes2 = g_variant_get_data_as_bytes (a);
4956 g_assert_false (g_bytes_equal (bytes, bytes2));
4958 g_bytes_unref (bytes);
4959 g_bytes_unref (bytes2);
4960 g_variant_unref (a);
4961 g_variant_unref (tuple);
4965 const GVariantType *type;
4971 test_print_context (void)
4973 ContextTest tests[] = {
4974 { NULL, "(1, 2, 3, 'abc", " ^^^^" },
4975 { NULL, "[1, 2, 3, 'str']", " ^ ^^^^^" },
4976 { G_VARIANT_TYPE_UINT16, "{ 'abc':'def' }", " ^^^^^^^^^^^^^^^" },
4977 { NULL, "<5", " ^" },
4978 { NULL, "'ab\\ux'", " ^ " },
4979 { NULL, "'ab\\U00efx'", " ^^^^ " }
4984 GError *error = NULL;
4986 for (i = 0; i < G_N_ELEMENTS (tests); i++)
4988 v = g_variant_parse (tests[i].type, tests[i].in, NULL, NULL, &error);
4990 s = g_variant_parse_error_print_context (error, tests[i].in);
4991 g_assert_nonnull (strstr (s, tests[i].out));
4993 g_clear_error (&error);
4998 test_error_quark (void)
5000 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
5001 g_assert_cmpuint (g_variant_parser_get_error_quark (), ==, g_variant_parse_error_quark ());
5002 G_GNUC_END_IGNORE_DEPRECATIONS
5006 test_stack_builder_init (void)
5008 GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE_BYTESTRING);
5011 g_variant_builder_add_value (&builder, g_variant_new_byte ('g'));
5012 g_variant_builder_add_value (&builder, g_variant_new_byte ('l'));
5013 g_variant_builder_add_value (&builder, g_variant_new_byte ('i'));
5014 g_variant_builder_add_value (&builder, g_variant_new_byte ('b'));
5015 g_variant_builder_add_value (&builder, g_variant_new_byte ('\0'));
5017 variant = g_variant_ref_sink (g_variant_builder_end (&builder));
5018 g_assert_nonnull (variant);
5019 g_assert_true (g_variant_type_equal (g_variant_get_type (variant),
5020 G_VARIANT_TYPE_BYTESTRING));
5021 g_assert_cmpuint (g_variant_n_children (variant), ==, 5);
5022 g_assert_cmpstr (g_variant_get_bytestring (variant), ==, "glib");
5023 g_variant_unref (variant);
5029 GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE_VARDICT);
5031 g_variant_builder_add (&builder, "{s@v}", "foo", g_variant_new_variant (g_variant_new_string ("FOO")));
5032 g_variant_builder_add (&builder, "{s@v}", "bar", g_variant_new_variant (g_variant_new_string ("BAR")));
5034 return g_variant_ref_sink (g_variant_builder_end (&builder));
5038 test_stack_dict_init (void)
5040 GVariant *asv = get_asv ();
5041 GVariantDict dict = G_VARIANT_DICT_INIT (asv);
5046 const gchar *str_value;
5048 g_assert_true (g_variant_dict_lookup (&dict, "foo", "&s", &str_value, NULL));
5049 g_assert_cmpstr (str_value, ==, "FOO");
5050 g_assert_true (g_variant_dict_lookup (&dict, "bar", "&s", &str_value, NULL));
5051 g_assert_cmpstr (str_value, ==, "BAR");
5053 g_variant_dict_insert_value (&dict, "baz", g_variant_new_string ("BAZ"));
5054 g_variant_dict_insert_value (&dict, "quux", g_variant_new_string ("QUUX"));
5056 g_assert_true (g_variant_dict_lookup (&dict, "baz", "&s", &str_value, NULL));
5057 g_assert_cmpstr (str_value, ==, "BAZ");
5058 g_assert_true (g_variant_dict_lookup (&dict, "quux", "&s", &str_value, NULL));
5059 g_assert_cmpstr (str_value, ==, "QUUX");
5061 variant = g_variant_ref_sink (g_variant_dict_end (&dict));
5062 g_assert_nonnull (variant);
5063 g_assert_true (g_variant_type_equal (g_variant_get_type (variant),
5064 G_VARIANT_TYPE_VARDICT));
5065 g_assert_cmpuint (g_variant_n_children (variant), ==, 4);
5067 g_variant_iter_init (&iter, variant);
5068 while (g_variant_iter_next (&iter, "{sv}", &key, &value))
5070 gchar *strup = g_ascii_strup (key, -1);
5072 g_assert_cmpstr (strup, ==, g_variant_get_string (value, NULL));
5075 g_variant_unref (value);
5078 g_variant_unref (asv);
5079 g_variant_unref (variant);
5082 /* Test checking arbitrary binary data for normal form. This time, it’s a tuple
5083 * with invalid element ends. */
5085 test_normal_checking_tuples (void)
5087 const guint8 data[] = {
5088 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
5089 'a', '(', 'a', 'o', 'a', 'o', 'a', 'a', 'o', 'a', 'a', 'o', ')'
5091 gsize size = sizeof (data);
5092 GVariant *variant = NULL;
5093 GVariant *normal_variant = NULL;
5095 variant = g_variant_new_from_data (G_VARIANT_TYPE_VARIANT, data, size,
5097 g_assert_nonnull (variant);
5099 normal_variant = g_variant_get_normal_form (variant);
5100 g_assert_nonnull (normal_variant);
5102 g_variant_unref (normal_variant);
5103 g_variant_unref (variant);
5106 /* Check that deeply nested variants are not considered in normal form when
5107 * deserialized from untrusted data.*/
5109 test_recursion_limits_variant_in_variant (void)
5111 GVariant *wrapper_variant = NULL;
5113 GBytes *bytes = NULL;
5114 GVariant *deserialised_variant = NULL;
5116 /* Construct a hierarchy of variants, containing a single string. This is just
5117 * below the maximum recursion level, as a series of nested variant types. */
5118 wrapper_variant = g_variant_new_string ("hello");
5120 for (i = 0; i < G_VARIANT_MAX_RECURSION_DEPTH - 1; i++)
5121 wrapper_variant = g_variant_new_variant (g_steal_pointer (&wrapper_variant));
5123 /* Serialize and deserialize it as untrusted data, to force normalisation. */
5124 bytes = g_variant_get_data_as_bytes (wrapper_variant);
5125 deserialised_variant = g_variant_new_from_bytes (G_VARIANT_TYPE_VARIANT,
5127 g_assert_nonnull (deserialised_variant);
5128 g_assert_true (g_variant_is_normal_form (deserialised_variant));
5130 g_bytes_unref (bytes);
5131 g_variant_unref (deserialised_variant);
5133 /* Wrap it once more. Normalisation should now fail. */
5134 wrapper_variant = g_variant_new_variant (g_steal_pointer (&wrapper_variant));
5136 bytes = g_variant_get_data_as_bytes (wrapper_variant);
5137 deserialised_variant = g_variant_new_from_bytes (G_VARIANT_TYPE_VARIANT,
5139 g_assert_nonnull (deserialised_variant);
5140 g_assert_false (g_variant_is_normal_form (deserialised_variant));
5142 g_variant_unref (deserialised_variant);
5144 /* Deserialize it again, but trusted this time. This should succeed. */
5145 deserialised_variant = g_variant_new_from_bytes (G_VARIANT_TYPE_VARIANT,
5147 g_assert_nonnull (deserialised_variant);
5148 g_assert_true (g_variant_is_normal_form (deserialised_variant));
5150 g_bytes_unref (bytes);
5151 g_variant_unref (deserialised_variant);
5152 g_variant_unref (wrapper_variant);
5155 /* Check that deeply nested arrays are not considered in normal form when
5156 * deserialized from untrusted data after being wrapped in a variant. This is
5157 * worth testing, because neither the deeply nested array, nor the variant,
5158 * have a static #GVariantType which is too deep — only when nested together do
5159 * they become too deep. */
5161 test_recursion_limits_array_in_variant (void)
5163 GVariant *child_variant = NULL;
5164 GVariant *wrapper_variant = NULL;
5166 GBytes *bytes = NULL;
5167 GVariant *deserialised_variant = NULL;
5169 /* Construct a hierarchy of arrays, containing a single string. This is just
5170 * below the maximum recursion level, all in a single definite type. */
5171 child_variant = g_variant_new_string ("hello");
5173 for (i = 0; i < G_VARIANT_MAX_RECURSION_DEPTH - 1; i++)
5174 child_variant = g_variant_new_array (NULL, &child_variant, 1);
5176 /* Serialize and deserialize it as untrusted data, to force normalisation. */
5177 bytes = g_variant_get_data_as_bytes (child_variant);
5178 deserialised_variant = g_variant_new_from_bytes (g_variant_get_type (child_variant),
5180 g_assert_nonnull (deserialised_variant);
5181 g_assert_true (g_variant_is_normal_form (deserialised_variant));
5183 g_bytes_unref (bytes);
5184 g_variant_unref (deserialised_variant);
5186 /* Wrap it in a variant. Normalisation should now fail. */
5187 wrapper_variant = g_variant_new_variant (g_steal_pointer (&child_variant));
5189 bytes = g_variant_get_data_as_bytes (wrapper_variant);
5190 deserialised_variant = g_variant_new_from_bytes (G_VARIANT_TYPE_VARIANT,
5192 g_assert_nonnull (deserialised_variant);
5193 g_assert_false (g_variant_is_normal_form (deserialised_variant));
5195 g_variant_unref (deserialised_variant);
5197 /* Deserialize it again, but trusted this time. This should succeed. */
5198 deserialised_variant = g_variant_new_from_bytes (G_VARIANT_TYPE_VARIANT,
5200 g_assert_nonnull (deserialised_variant);
5201 g_assert_true (g_variant_is_normal_form (deserialised_variant));
5203 g_bytes_unref (bytes);
5204 g_variant_unref (deserialised_variant);
5205 g_variant_unref (wrapper_variant);
5208 /* Test that a nested array with invalid values in its offset table (which point
5209 * from the inner to the outer array) is normalised successfully without
5210 * looping infinitely. */
5212 test_normal_checking_array_offsets_overlapped (void)
5214 const guint8 data[] = {
5217 gsize size = sizeof (data);
5218 GVariant *variant = NULL;
5219 GVariant *normal_variant = NULL;
5220 GVariant *expected_variant = NULL;
5222 variant = g_variant_new_from_data (G_VARIANT_TYPE ("aay"), data, size,
5224 g_assert_nonnull (variant);
5226 normal_variant = g_variant_get_normal_form (variant);
5227 g_assert_nonnull (normal_variant);
5229 expected_variant = g_variant_new_parsed ("[@ay [], []]");
5230 g_assert_cmpvariant (normal_variant, expected_variant);
5232 g_assert_cmpmem (g_variant_get_data (normal_variant), g_variant_get_size (normal_variant),
5233 g_variant_get_data (expected_variant), g_variant_get_size (expected_variant));
5235 g_variant_unref (expected_variant);
5236 g_variant_unref (normal_variant);
5237 g_variant_unref (variant);
5240 /* Test that an array with invalidly large values in its offset table is
5241 * normalised successfully without looping infinitely. */
5243 test_normal_checking_array_offsets (void)
5245 const guint8 data[] = {
5246 0x07, 0xe5, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00,
5247 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'g',
5249 gsize size = sizeof (data);
5250 GVariant *variant = NULL;
5251 GVariant *normal_variant = NULL;
5253 variant = g_variant_new_from_data (G_VARIANT_TYPE_VARIANT, data, size,
5255 g_assert_nonnull (variant);
5257 normal_variant = g_variant_get_normal_form (variant);
5258 g_assert_nonnull (normal_variant);
5260 g_variant_unref (normal_variant);
5261 g_variant_unref (variant);
5264 /* This is a regression test that we can't have non-normal values that take up
5265 * significantly more space than the normal equivalent, by specifying the
5266 * offset table entries so that array elements overlap.
5268 * See https://gitlab.gnome.org/GNOME/glib/-/issues/2121#note_832242 */
5270 test_normal_checking_array_offsets2 (void)
5272 const guint8 data[] = {
5282 gsize size = sizeof (data);
5283 const GVariantType *aaaaaaas = G_VARIANT_TYPE ("aaaaaaas");
5284 GVariant *variant = NULL;
5285 GVariant *normal_variant = NULL;
5286 GVariant *expected = NULL;
5288 variant = g_variant_new_from_data (aaaaaaas, data, size, FALSE, NULL, NULL);
5289 g_assert_nonnull (variant);
5291 normal_variant = g_variant_get_normal_form (variant);
5292 g_assert_nonnull (normal_variant);
5293 g_assert_cmpuint (g_variant_get_size (normal_variant), <=, size * 2);
5295 expected = g_variant_new_parsed (
5296 "[[[[[[['hi', '', ''], [], []], [], []], [], []], [], []], [], []], [], []]");
5297 g_assert_cmpvariant (expected, variant);
5298 g_assert_cmpvariant (expected, normal_variant);
5300 g_variant_unref (expected);
5301 g_variant_unref (normal_variant);
5302 g_variant_unref (variant);
5305 /* Test that an otherwise-valid serialised GVariant is considered non-normal if
5306 * its offset table entries are too wide.
5308 * See §2.3.6 (Framing Offsets) of the GVariant specification. */
5310 test_normal_checking_array_offsets_minimal_sized (void)
5312 GVariantBuilder builder;
5314 GVariant *aay_constructed = NULL;
5315 const guint8 *data = NULL;
5316 guint8 *data_owned = NULL;
5317 GVariant *aay_deserialised = NULL;
5318 GVariant *aay_normalised = NULL;
5320 /* Construct an array of type aay, consisting of 128 elements which are each
5321 * an empty array, i.e. `[[] * 128]`. This is chosen because the inner
5322 * elements are variable sized (making the outer array variable sized, so it
5323 * must have an offset table), but they are also zero-sized when serialised.
5324 * So the serialised representation of @aay_constructed consists entirely of
5325 * its offset table, which is entirely zeroes.
5327 * The array is chosen to be 128 elements long because that means offset
5328 * table entries which are 1 byte long. If the elements in the array were
5329 * non-zero-sized (to the extent that the overall array is ≥256 bytes long),
5330 * the offset table entries would end up being 2 bytes long. */
5331 g_variant_builder_init (&builder, G_VARIANT_TYPE ("aay"));
5333 for (i = 0; i < 128; i++)
5334 g_variant_builder_add_value (&builder, g_variant_new_array (G_VARIANT_TYPE_BYTE, NULL, 0));
5336 aay_constructed = g_variant_builder_end (&builder);
5338 /* Verify that the constructed array is in normal form, and its serialised
5339 * form is `b'\0' * 128`. */
5340 g_assert_true (g_variant_is_normal_form (aay_constructed));
5341 g_assert_cmpuint (g_variant_n_children (aay_constructed), ==, 128);
5342 g_assert_cmpuint (g_variant_get_size (aay_constructed), ==, 128);
5344 data = g_variant_get_data (aay_constructed);
5345 for (i = 0; i < g_variant_get_size (aay_constructed); i++)
5346 g_assert_cmpuint (data[i], ==, 0);
5348 /* Construct a serialised `aay` GVariant which is `b'\0' * 256`. This has to
5349 * be a non-normal form of `[[] * 128]`, with 2-byte-long offset table
5350 * entries, because each offset table entry has to be able to reference all of
5351 * the byte boundaries in the container. All the entries in the offset table
5352 * are zero, so all the elements of the array are zero-sized. */
5353 data = data_owned = g_malloc0 (256);
5354 aay_deserialised = g_variant_new_from_data (G_VARIANT_TYPE ("aay"),
5359 g_steal_pointer (&data_owned));
5361 g_assert_false (g_variant_is_normal_form (aay_deserialised));
5362 g_assert_cmpuint (g_variant_n_children (aay_deserialised), ==, 128);
5363 g_assert_cmpuint (g_variant_get_size (aay_deserialised), ==, 256);
5365 data = g_variant_get_data (aay_deserialised);
5366 for (i = 0; i < g_variant_get_size (aay_deserialised); i++)
5367 g_assert_cmpuint (data[i], ==, 0);
5369 /* Get its normal form. That should change the serialised size. */
5370 aay_normalised = g_variant_get_normal_form (aay_deserialised);
5372 g_assert_true (g_variant_is_normal_form (aay_normalised));
5373 g_assert_cmpuint (g_variant_n_children (aay_normalised), ==, 128);
5374 g_assert_cmpuint (g_variant_get_size (aay_normalised), ==, 128);
5376 data = g_variant_get_data (aay_normalised);
5377 for (i = 0; i < g_variant_get_size (aay_normalised); i++)
5378 g_assert_cmpuint (data[i], ==, 0);
5380 g_variant_unref (aay_normalised);
5381 g_variant_unref (aay_deserialised);
5382 g_variant_unref (aay_constructed);
5385 /* Test that a tuple with invalidly large values in its offset table is
5386 * normalised successfully without looping infinitely. */
5388 test_normal_checking_tuple_offsets (void)
5390 const guint8 data[] = {
5391 0x07, 0xe5, 0x00, 0x07, 0x00, 0x07,
5392 '(', 'a', 's', 'a', 's', 'a', 's', 'a', 's', 'a', 's', 'a', 's', ')',
5394 gsize size = sizeof (data);
5395 GVariant *variant = NULL;
5396 GVariant *normal_variant = NULL;
5398 variant = g_variant_new_from_data (G_VARIANT_TYPE_VARIANT, data, size,
5400 g_assert_nonnull (variant);
5402 normal_variant = g_variant_get_normal_form (variant);
5403 g_assert_nonnull (normal_variant);
5405 g_variant_unref (normal_variant);
5406 g_variant_unref (variant);
5409 /* This is a regression test that we can't have non-normal values that take up
5410 * significantly more space than the normal equivalent, by specifying the
5411 * offset table entries so that tuple elements overlap.
5413 * See https://gitlab.gnome.org/GNOME/glib/-/issues/2121#note_838503 and
5414 * https://gitlab.gnome.org/GNOME/glib/-/issues/2121#note_838513 */
5416 test_normal_checking_tuple_offsets2 (void)
5418 const GVariantType *data_type = G_VARIANT_TYPE ("(yyaiyyaiyy)");
5419 const guint8 data[] = {
5420 0x12, 0x34, 0x56, 0x78, 0x01,
5422 ^───────────────────┘
5427 ^^^^ Framing offsets
5430 /* If this variant was encoded normally, it would be something like this:
5431 * 0x12, 0x34, pad, pad, [array bytes], 0x56, 0x78, pad, pad, [array bytes], 0x9A, 0xBC, 0xXX
5432 * ^─────────────────────────────────────────────────────┘
5437 * ^^^^ Framing offsets
5440 gsize size = sizeof (data);
5441 GVariant *variant = NULL;
5442 GVariant *normal_variant = NULL;
5443 GVariant *expected = NULL;
5445 variant = g_variant_new_from_data (data_type, data, size, FALSE, NULL, NULL);
5446 g_assert_nonnull (variant);
5448 normal_variant = g_variant_get_normal_form (variant);
5449 g_assert_nonnull (normal_variant);
5450 g_assert_cmpuint (g_variant_get_size (normal_variant), <=, size * 3);
5452 expected = g_variant_new_parsed (
5453 "@(yyaiyyaiyy) (0x12, 0x34, [], 0x00, 0x00, [], 0x00, 0x00)");
5454 g_assert_cmpvariant (expected, variant);
5455 g_assert_cmpvariant (expected, normal_variant);
5457 g_variant_unref (expected);
5458 g_variant_unref (normal_variant);
5459 g_variant_unref (variant);
5462 /* This is a regression test that overlapping entries in the offset table are
5463 * decoded consistently, even though they’re non-normal.
5465 * See https://gitlab.gnome.org/GNOME/glib/-/issues/2121#note_910935 */
5467 test_normal_checking_tuple_offsets3 (void)
5469 /* The expected decoding of this non-normal byte stream is complex. See
5470 * section 2.7.3 (Handling Non-Normal Serialised Data) of the GVariant
5473 * The rule “Child Values Overlapping Framing Offsets” from the specification
5474 * says that the first `ay` must be decoded as `[0x01]` even though it
5475 * overlaps the first byte of the offset table. However, since commit
5476 * 7eedcd76f7d5b8c98fa60013e1fe6e960bf19df3, GLib explicitly doesn’t allow
5477 * this as it’s exploitable. So the first `ay` must be given a default value.
5479 * The second and third `ay`s must be given default values because of rule
5480 * “End Boundary Precedes Start Boundary”.
5482 * The `i` must be given a default value because of rule “Start or End
5483 * Boundary of a Child Falls Outside the Container”.
5485 const GVariantType *data_type = G_VARIANT_TYPE ("(ayayiay)");
5486 const guint8 data[] = {
5491 ^^^^^^^^^^ 1st ay, bytes 0-2 (but given a default value anyway, see above)
5495 ^^^^^^^^^^ Framing offsets
5498 gsize size = sizeof (data);
5499 GVariant *variant = NULL;
5500 GVariant *normal_variant = NULL;
5501 GVariant *expected = NULL;
5503 variant = g_variant_new_from_data (data_type, data, size, FALSE, NULL, NULL);
5504 g_assert_nonnull (variant);
5506 g_assert_false (g_variant_is_normal_form (variant));
5508 normal_variant = g_variant_get_normal_form (variant);
5509 g_assert_nonnull (normal_variant);
5510 g_assert_cmpuint (g_variant_get_size (normal_variant), <=, size * 3);
5512 expected = g_variant_new_parsed ("@(ayayiay) ([], [], 0, [])");
5513 g_assert_cmpvariant (expected, variant);
5514 g_assert_cmpvariant (expected, normal_variant);
5516 g_variant_unref (expected);
5517 g_variant_unref (normal_variant);
5518 g_variant_unref (variant);
5521 /* This is a regression test that overlapping entries in the offset table are
5522 * decoded consistently, even though they’re non-normal.
5524 * See https://gitlab.gnome.org/GNOME/glib/-/issues/2121#note_910935 */
5526 test_normal_checking_tuple_offsets4 (void)
5528 /* The expected decoding of this non-normal byte stream is complex. See
5529 * section 2.7.3 (Handling Non-Normal Serialised Data) of the GVariant
5532 * The rule “Child Values Overlapping Framing Offsets” from the specification
5533 * says that the first `ay` must be decoded as `[0x01]` even though it
5534 * overlaps the first byte of the offset table. However, since commit
5535 * 7eedcd76f7d5b8c98fa60013e1fe6e960bf19df3, GLib explicitly doesn’t allow
5536 * this as it’s exploitable. So the first `ay` must be given a default value.
5538 * The second `ay` must be given a default value because of rule “End Boundary
5539 * Precedes Start Boundary”.
5541 * The third `ay` must be given a default value because its framing offsets
5542 * overlap that of the first `ay`.
5544 const GVariantType *data_type = G_VARIANT_TYPE ("(ayayay)");
5545 const guint8 data[] = {
5550 ^^^^^^^^^^ 1st ay, bytes 0-2 (but given a default value anyway, see above)
5553 ^^^^^^^^^^ Framing offsets
5556 gsize size = sizeof (data);
5557 GVariant *variant = NULL;
5558 GVariant *normal_variant = NULL;
5559 GVariant *expected = NULL;
5561 variant = g_variant_new_from_data (data_type, data, size, FALSE, NULL, NULL);
5562 g_assert_nonnull (variant);
5564 g_assert_false (g_variant_is_normal_form (variant));
5566 normal_variant = g_variant_get_normal_form (variant);
5567 g_assert_nonnull (normal_variant);
5568 g_assert_cmpuint (g_variant_get_size (normal_variant), <=, size * 3);
5570 expected = g_variant_new_parsed ("@(ayayay) ([], [], [])");
5571 g_assert_cmpvariant (expected, variant);
5572 g_assert_cmpvariant (expected, normal_variant);
5574 g_variant_unref (expected);
5575 g_variant_unref (normal_variant);
5576 g_variant_unref (variant);
5579 /* This is a regression test that dereferencing the first element in the offset
5580 * table doesn’t dereference memory before the start of the GVariant. The first
5581 * element in the offset table gives the offset of the final member in the
5582 * tuple (the offset table is stored in reverse), and the position of this final
5583 * member is needed to check that none of the tuple members overlap with the
5586 * See https://gitlab.gnome.org/GNOME/glib/-/issues/2840 */
5588 test_normal_checking_tuple_offsets5 (void)
5590 /* A tuple of type (sss) in normal form would have an offset table with two
5592 * - The first entry (lowest index in the table) gives the offset of the
5593 * third `s` in the tuple, as the offset table is reversed compared to the
5595 * - The second entry (highest index in the table) gives the offset of the
5596 * second `s` in the tuple.
5597 * - The offset of the first `s` in the tuple is always 0.
5599 * See §2.5.4 (Structures) of the GVariant specification for details, noting
5600 * that the table is only layed out this way because all three members of the
5601 * tuple have non-fixed sizes.
5603 * It’s not clear whether the 0xaa data of this variant is part of the strings
5604 * in the tuple, or part of the offset table. It doesn’t really matter. This
5605 * is a regression test to check that the code to validate the offset table
5606 * doesn’t unconditionally try to access the first entry in the offset table
5607 * by subtracting the table size from the end of the GVariant data.
5609 * In this non-normal case, that would result in an address off the start of
5610 * the GVariant data, and an out-of-bounds read, because the GVariant is one
5611 * byte long, but the offset table is calculated as two bytes long (with 1B
5612 * sized entries) from the tuple’s type.
5614 const GVariantType *data_type = G_VARIANT_TYPE ("(sss)");
5615 const guint8 data[] = { 0xaa };
5616 gsize size = sizeof (data);
5617 GVariant *variant = NULL;
5618 GVariant *normal_variant = NULL;
5619 GVariant *expected = NULL;
5621 g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2840");
5623 variant = g_variant_new_from_data (data_type, data, size, FALSE, NULL, NULL);
5624 g_assert_nonnull (variant);
5626 g_assert_false (g_variant_is_normal_form (variant));
5628 normal_variant = g_variant_get_normal_form (variant);
5629 g_assert_nonnull (normal_variant);
5631 expected = g_variant_new_parsed ("('', '', '')");
5632 g_assert_cmpvariant (expected, variant);
5633 g_assert_cmpvariant (expected, normal_variant);
5635 g_variant_unref (expected);
5636 g_variant_unref (normal_variant);
5637 g_variant_unref (variant);
5640 /* Test that an otherwise-valid serialised GVariant is considered non-normal if
5641 * its offset table entries are too wide.
5643 * See §2.3.6 (Framing Offsets) of the GVariant specification. */
5645 test_normal_checking_tuple_offsets_minimal_sized (void)
5647 GString *type_string = NULL;
5648 GVariantBuilder builder;
5650 GVariant *ray_constructed = NULL;
5651 const guint8 *data = NULL;
5652 guint8 *data_owned = NULL;
5653 GVariant *ray_deserialised = NULL;
5654 GVariant *ray_normalised = NULL;
5656 /* Construct a tuple of type (ay…ay), consisting of 129 members which are each
5657 * an empty array, i.e. `([] * 129)`. This is chosen because the inner
5658 * members are variable sized, so the outer tuple must have an offset table,
5659 * but they are also zero-sized when serialised. So the serialised
5660 * representation of @ray_constructed consists entirely of its offset table,
5661 * which is entirely zeroes.
5663 * The tuple is chosen to be 129 members long because that means it has 128
5664 * offset table entries which are 1 byte long each. If the members in the
5665 * tuple were non-zero-sized (to the extent that the overall tuple is ≥256
5666 * bytes long), the offset table entries would end up being 2 bytes long.
5668 * 129 members are used unlike 128 array elements in
5669 * test_normal_checking_array_offsets_minimal_sized(), because the last member
5670 * in a tuple never needs an offset table entry. */
5671 type_string = g_string_new ("");
5672 g_string_append_c (type_string, '(');
5673 for (i = 0; i < 129; i++)
5674 g_string_append (type_string, "ay");
5675 g_string_append_c (type_string, ')');
5677 g_variant_builder_init (&builder, G_VARIANT_TYPE (type_string->str));
5679 for (i = 0; i < 129; i++)
5680 g_variant_builder_add_value (&builder, g_variant_new_array (G_VARIANT_TYPE_BYTE, NULL, 0));
5682 ray_constructed = g_variant_builder_end (&builder);
5684 /* Verify that the constructed tuple is in normal form, and its serialised
5685 * form is `b'\0' * 128`. */
5686 g_assert_true (g_variant_is_normal_form (ray_constructed));
5687 g_assert_cmpuint (g_variant_n_children (ray_constructed), ==, 129);
5688 g_assert_cmpuint (g_variant_get_size (ray_constructed), ==, 128);
5690 data = g_variant_get_data (ray_constructed);
5691 for (i = 0; i < g_variant_get_size (ray_constructed); i++)
5692 g_assert_cmpuint (data[i], ==, 0);
5694 /* Construct a serialised `(ay…ay)` GVariant which is `b'\0' * 256`. This has
5695 * to be a non-normal form of `([] * 129)`, with 2-byte-long offset table
5696 * entries, because each offset table entry has to be able to reference all of
5697 * the byte boundaries in the container. All the entries in the offset table
5698 * are zero, so all the members of the tuple are zero-sized. */
5699 data = data_owned = g_malloc0 (256);
5700 ray_deserialised = g_variant_new_from_data (G_VARIANT_TYPE (type_string->str),
5705 g_steal_pointer (&data_owned));
5707 g_assert_false (g_variant_is_normal_form (ray_deserialised));
5708 g_assert_cmpuint (g_variant_n_children (ray_deserialised), ==, 129);
5709 g_assert_cmpuint (g_variant_get_size (ray_deserialised), ==, 256);
5711 data = g_variant_get_data (ray_deserialised);
5712 for (i = 0; i < g_variant_get_size (ray_deserialised); i++)
5713 g_assert_cmpuint (data[i], ==, 0);
5715 /* Get its normal form. That should change the serialised size. */
5716 ray_normalised = g_variant_get_normal_form (ray_deserialised);
5718 g_assert_true (g_variant_is_normal_form (ray_normalised));
5719 g_assert_cmpuint (g_variant_n_children (ray_normalised), ==, 129);
5720 g_assert_cmpuint (g_variant_get_size (ray_normalised), ==, 128);
5722 data = g_variant_get_data (ray_normalised);
5723 for (i = 0; i < g_variant_get_size (ray_normalised); i++)
5724 g_assert_cmpuint (data[i], ==, 0);
5726 g_variant_unref (ray_normalised);
5727 g_variant_unref (ray_deserialised);
5728 g_variant_unref (ray_constructed);
5729 g_string_free (type_string, TRUE);
5732 /* Test that an empty object path is normalised successfully to the base object
5735 test_normal_checking_empty_object_path (void)
5737 const guint8 data[] = {
5738 0x20, 0x20, 0x00, 0x00, 0x00, 0x00,
5739 '(', 'h', '(', 'a', 'i', 'a', 'b', 'i', 'o', ')', ')',
5741 gsize size = sizeof (data);
5742 GVariant *variant = NULL;
5743 GVariant *normal_variant = NULL;
5745 variant = g_variant_new_from_data (G_VARIANT_TYPE_VARIANT, data, size,
5747 g_assert_nonnull (variant);
5749 normal_variant = g_variant_get_normal_form (variant);
5750 g_assert_nonnull (normal_variant);
5752 g_variant_unref (normal_variant);
5753 g_variant_unref (variant);
5756 /* Test that constructing a #GVariant from data which is not correctly aligned
5757 * for the variant type is OK, by loading a variant from data at various offsets
5758 * which are aligned and unaligned. When unaligned, a slow construction path
5759 * should be taken. */
5761 test_unaligned_construction (void)
5763 const guint8 data[] = {
5764 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
5765 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
5767 GVariant *variant = NULL;
5768 GVariant *normal_variant = NULL;
5771 const GVariantType *type;
5775 { G_VARIANT_TYPE_UINT64, sizeof (guint64), sizeof (guint64) },
5776 { G_VARIANT_TYPE_UINT32, sizeof (guint32), sizeof (guint32) },
5777 { G_VARIANT_TYPE_UINT16, sizeof (guint16), sizeof (guint16) },
5778 { G_VARIANT_TYPE_BYTE, sizeof (guint8), 3 },
5781 G_STATIC_ASSERT (sizeof (guint64) * 2 <= sizeof (data));
5783 for (i = 0; i < G_N_ELEMENTS (vectors); i++)
5785 for (offset = 0; offset < vectors[i].max_offset; offset++)
5787 variant = g_variant_new_from_data (vectors[i].type, data + offset,
5790 g_assert_nonnull (variant);
5792 normal_variant = g_variant_get_normal_form (variant);
5793 g_assert_nonnull (normal_variant);
5795 g_variant_unref (normal_variant);
5796 g_variant_unref (variant);
5802 main (int argc, char **argv)
5806 g_test_init (&argc, &argv, NULL);
5808 g_test_add_func ("/gvariant/type", test_gvarianttype);
5809 g_test_add_func ("/gvariant/type/string-scan/recursion/tuple",
5810 test_gvarianttype_string_scan_recursion_tuple);
5811 g_test_add_func ("/gvariant/type/string-scan/recursion/array",
5812 test_gvarianttype_string_scan_recursion_array);
5813 g_test_add_func ("/gvariant/typeinfo", test_gvarianttypeinfo);
5814 g_test_add_func ("/gvariant/serialiser/maybe", test_maybes);
5815 g_test_add_func ("/gvariant/serialiser/array", test_arrays);
5816 g_test_add_func ("/gvariant/serialiser/tuple", test_tuples);
5817 g_test_add_func ("/gvariant/serialiser/variant", test_variants);
5818 g_test_add_func ("/gvariant/serialiser/strings", test_strings);
5819 g_test_add_func ("/gvariant/serialiser/byteswap", test_byteswaps);
5820 g_test_add_func ("/gvariant/serialiser/children", test_serialiser_children);
5822 for (i = 1; i <= 20; i += 4)
5826 testname = g_strdup_printf ("/gvariant/serialiser/fuzz/%u%%", i);
5827 g_test_add_data_func (testname, GINT_TO_POINTER (i),
5828 (gpointer) test_fuzzes);
5832 g_test_add_func ("/gvariant/string", test_string);
5833 g_test_add_func ("/gvariant/utf8", test_utf8);
5834 g_test_add_func ("/gvariant/containers", test_containers);
5835 g_test_add_func ("/gvariant/format-strings", test_format_strings);
5836 g_test_add_func ("/gvariant/invalid-varargs", test_invalid_varargs);
5837 g_test_add_func ("/gvariant/varargs", test_varargs);
5838 g_test_add_func ("/gvariant/varargs/subprocess/empty-array", test_varargs_empty_array);
5839 g_test_add_func ("/gvariant/valist", test_valist);
5840 g_test_add_func ("/gvariant/builder-memory", test_builder_memory);
5841 g_test_add_func ("/gvariant/hashing", test_hashing);
5842 g_test_add_func ("/gvariant/byteswap", test_gv_byteswap);
5843 g_test_add_func ("/gvariant/byteswap/non-normal-non-aligned", test_gv_byteswap_non_normal_non_aligned);
5844 g_test_add_func ("/gvariant/parser", test_parses);
5845 g_test_add_func ("/gvariant/parser/integer-bounds", test_parser_integer_bounds);
5846 g_test_add_func ("/gvariant/parser/recursion", test_parser_recursion);
5847 g_test_add_func ("/gvariant/parser/recursion/typedecls", test_parser_recursion_typedecls);
5848 g_test_add_func ("/gvariant/parser/recursion/maybes", test_parser_recursion_maybes);
5849 g_test_add_func ("/gvariant/parse-failures", test_parse_failures);
5850 g_test_add_func ("/gvariant/parse-positional", test_parse_positional);
5851 g_test_add_func ("/gvariant/parse/subprocess/bad-format-char", test_parse_bad_format_char);
5852 g_test_add_func ("/gvariant/parse/subprocess/bad-format-string", test_parse_bad_format_string);
5853 g_test_add_func ("/gvariant/parse/subprocess/bad-args", test_parse_bad_args);
5854 g_test_add_func ("/gvariant/floating", test_floating);
5855 g_test_add_func ("/gvariant/bytestring", test_bytestring);
5856 g_test_add_func ("/gvariant/lookup-value", test_lookup_value);
5857 g_test_add_func ("/gvariant/lookup", test_lookup);
5858 g_test_add_func ("/gvariant/compare", test_compare);
5859 g_test_add_func ("/gvariant/equal", test_equal);
5860 g_test_add_func ("/gvariant/fixed-array", test_fixed_array);
5861 g_test_add_func ("/gvariant/check-format-string", test_check_format_string);
5863 g_test_add_func ("/gvariant/checksum-basic", test_checksum_basic);
5864 g_test_add_func ("/gvariant/checksum-nested", test_checksum_nested);
5866 g_test_add_func ("/gvariant/gbytes", test_gbytes);
5867 g_test_add_func ("/gvariant/print-context", test_print_context);
5868 g_test_add_func ("/gvariant/error-quark", test_error_quark);
5870 g_test_add_func ("/gvariant/stack-builder-init", test_stack_builder_init);
5871 g_test_add_func ("/gvariant/stack-dict-init", test_stack_dict_init);
5873 g_test_add_func ("/gvariant/normal-checking/tuples",
5874 test_normal_checking_tuples);
5875 g_test_add_func ("/gvariant/normal-checking/array-offsets/overlapped",
5876 test_normal_checking_array_offsets_overlapped);
5877 g_test_add_func ("/gvariant/normal-checking/array-offsets",
5878 test_normal_checking_array_offsets);
5879 g_test_add_func ("/gvariant/normal-checking/array-offsets2",
5880 test_normal_checking_array_offsets2);
5881 g_test_add_func ("/gvariant/normal-checking/array-offsets/minimal-sized",
5882 test_normal_checking_array_offsets_minimal_sized);
5883 g_test_add_func ("/gvariant/normal-checking/tuple-offsets",
5884 test_normal_checking_tuple_offsets);
5885 g_test_add_func ("/gvariant/normal-checking/tuple-offsets2",
5886 test_normal_checking_tuple_offsets2);
5887 g_test_add_func ("/gvariant/normal-checking/tuple-offsets3",
5888 test_normal_checking_tuple_offsets3);
5889 g_test_add_func ("/gvariant/normal-checking/tuple-offsets4",
5890 test_normal_checking_tuple_offsets4);
5891 g_test_add_func ("/gvariant/normal-checking/tuple-offsets5",
5892 test_normal_checking_tuple_offsets5);
5893 g_test_add_func ("/gvariant/normal-checking/tuple-offsets/minimal-sized",
5894 test_normal_checking_tuple_offsets_minimal_sized);
5895 g_test_add_func ("/gvariant/normal-checking/empty-object-path",
5896 test_normal_checking_empty_object_path);
5898 g_test_add_func ("/gvariant/recursion-limits/variant-in-variant",
5899 test_recursion_limits_variant_in_variant);
5900 g_test_add_func ("/gvariant/recursion-limits/array-in-variant",
5901 test_recursion_limits_array_in_variant);
5903 g_test_add_func ("/gvariant/unaligned-construction",
5904 test_unaligned_construction);
5906 return g_test_run ();