2 * Copyright © 2010 Codethink Limited
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the licence, or (at your option) any later version.
9 * See the included COPYING file for more information.
11 * Author: Ryan Lortie <desrt@desrt.ca>
14 #include <glib/gvariant-internal.h>
19 #define BASIC "bynqiuxthdsog?"
20 #define N_BASIC (G_N_ELEMENTS (BASIC) - 1)
22 #define INVALIDS "cefjklpwz&@^$"
23 #define N_INVALIDS (G_N_ELEMENTS (INVALIDS) - 1)
25 /* see comment in gvariant-serialiser.c about this madness.
27 * we use this to get testing of non-strictly-aligned GVariant instances
28 * on machines that can tolerate it. it is necessary to support this
29 * because some systems have malloc() that returns non-8-aligned
30 * pointers. it is necessary to have special support in the tests
31 * because on most machines malloc() is 8-aligned.
33 #define ALIGN_BITS (sizeof (struct { char a; union { \
34 guint64 x; void *y; gdouble z; } b; }) - 9)
37 randomly (gdouble prob)
39 return g_test_rand_double_range (0, 1) < prob;
44 append_tuple_type_string (GString *, GString *, gboolean, gint);
46 /* append a random GVariantType to a GString
47 * append a description of the type to another GString
48 * return what the type is
51 append_type_string (GString *string,
56 if (!depth-- || randomly (0.3))
58 gchar b = BASIC[g_test_rand_int_range (0, N_BASIC - definite)];
59 g_string_append_c (string, b);
60 g_string_append_c (description, b);
65 return g_variant_type_copy (G_VARIANT_TYPE_BOOLEAN);
67 return g_variant_type_copy (G_VARIANT_TYPE_BYTE);
69 return g_variant_type_copy (G_VARIANT_TYPE_INT16);
71 return g_variant_type_copy (G_VARIANT_TYPE_UINT16);
73 return g_variant_type_copy (G_VARIANT_TYPE_INT32);
75 return g_variant_type_copy (G_VARIANT_TYPE_UINT32);
77 return g_variant_type_copy (G_VARIANT_TYPE_INT64);
79 return g_variant_type_copy (G_VARIANT_TYPE_UINT64);
81 return g_variant_type_copy (G_VARIANT_TYPE_HANDLE);
83 return g_variant_type_copy (G_VARIANT_TYPE_DOUBLE);
85 return g_variant_type_copy (G_VARIANT_TYPE_STRING);
87 return g_variant_type_copy (G_VARIANT_TYPE_OBJECT_PATH);
89 return g_variant_type_copy (G_VARIANT_TYPE_SIGNATURE);
91 return g_variant_type_copy (G_VARIANT_TYPE_BASIC);
93 g_assert_not_reached ();
100 switch (g_test_rand_int_range (0, definite ? 5 : 7))
104 GVariantType *element;
106 g_string_append_c (string, 'a');
107 g_string_append (description, "a of ");
108 element = append_type_string (string, description,
110 result = g_variant_type_new_array (element);
111 g_variant_type_free (element);
114 g_assert (g_variant_type_is_array (result));
119 GVariantType *element;
121 g_string_append_c (string, 'm');
122 g_string_append (description, "m of ");
123 element = append_type_string (string, description,
125 result = g_variant_type_new_maybe (element);
126 g_variant_type_free (element);
129 g_assert (g_variant_type_is_maybe (result));
133 result = append_tuple_type_string (string, description,
136 g_assert (g_variant_type_is_tuple (result));
141 GVariantType *key, *value;
143 g_string_append_c (string, '{');
144 g_string_append (description, "e of [");
145 key = append_type_string (string, description, definite, 0);
146 g_string_append (description, ", ");
147 value = append_type_string (string, description, definite, depth);
148 g_string_append_c (description, ']');
149 g_string_append_c (string, '}');
150 result = g_variant_type_new_dict_entry (key, value);
151 g_variant_type_free (key);
152 g_variant_type_free (value);
155 g_assert (g_variant_type_is_dict_entry (result));
159 g_string_append_c (string, 'v');
160 g_string_append_c (description, 'V');
161 result = g_variant_type_copy (G_VARIANT_TYPE_VARIANT);
162 g_assert (g_variant_type_equal (result, G_VARIANT_TYPE_VARIANT));
166 g_string_append_c (string, '*');
167 g_string_append_c (description, 'S');
168 result = g_variant_type_copy (G_VARIANT_TYPE_ANY);
169 g_assert (g_variant_type_equal (result, G_VARIANT_TYPE_ANY));
173 g_string_append_c (string, 'r');
174 g_string_append_c (description, 'R');
175 result = g_variant_type_copy (G_VARIANT_TYPE_TUPLE);
176 g_assert (g_variant_type_is_tuple (result));
180 g_assert_not_reached ();
187 static GVariantType *
188 append_tuple_type_string (GString *string,
189 GString *description,
193 GVariantType *result, *other_result;
194 GVariantType **types;
198 g_string_append_c (string, '(');
199 g_string_append (description, "t of [");
201 size = g_test_rand_int_range (0, 20);
202 types = g_new (GVariantType *, size + 1);
204 for (i = 0; i < size; i++)
206 types[i] = append_type_string (string, description, definite, depth);
209 g_string_append (description, ", ");
214 g_string_append_c (description, ']');
215 g_string_append_c (string, ')');
217 result = g_variant_type_new_tuple ((gpointer) types, size);
218 other_result = g_variant_type_new_tuple ((gpointer) types, -1);
219 g_assert (g_variant_type_equal (result, other_result));
220 g_variant_type_free (other_result);
221 for (i = 0; i < size; i++)
222 g_variant_type_free (types[i]);
228 /* given a valid type string, make it invalid */
230 invalid_mutation (const gchar *type_string)
232 gboolean have_parens, have_braces;
234 /* it's valid, so '(' implies ')' and same for '{' and '}' */
235 have_parens = strchr (type_string, '(') != NULL;
236 have_braces = strchr (type_string, '{') != NULL;
238 if (have_parens && have_braces && randomly (0.3))
240 /* swap a paren and a brace */
246 new = g_strdup (type_string);
256 /* count number of parens/braces */
257 while ((pp = strchr (pp + 1, p))) np++;
258 while ((bp = strchr (bp + 1, b))) nb++;
260 /* randomly pick one of each */
261 np = g_test_rand_int_range (0, np) + 1;
262 nb = g_test_rand_int_range (0, nb) + 1;
266 while (np--) pp = strchr (pp + 1, p);
267 while (nb--) bp = strchr (bp + 1, b);
270 g_assert (*bp == b && *pp == p);
277 if ((have_parens || have_braces) && randomly (0.3))
279 /* drop a paren/brace */
286 if (randomly (0.5)) p = '('; else p = ')';
288 if (randomly (0.5)) p = '{'; else p = '}';
290 new = g_strdup (type_string);
294 while ((pp = strchr (pp + 1, p))) np++;
295 np = g_test_rand_int_range (0, np) + 1;
297 while (np--) pp = strchr (pp + 1, p);
309 /* else, perform a random mutation at a random point */
317 /* insert a paren/brace */
319 if (randomly (0.5)) p = '('; else p = ')';
321 if (randomly (0.5)) p = '{'; else p = '}';
323 else if (randomly (0.5))
326 p = INVALIDS[g_test_rand_int_range (0, N_INVALIDS)];
335 length = strlen (type_string);
336 new = g_malloc (length + 2);
337 n = g_test_rand_int_range (0, length);
338 memcpy (new, type_string, n);
340 memcpy (new + n + 1, type_string + n, length - n);
341 new[length + 1] = '\0';
347 /* describe a type using the same language as is generated
348 * while generating the type with append_type_string
351 describe_type (const GVariantType *type)
355 if (g_variant_type_is_container (type))
357 g_assert (!g_variant_type_is_basic (type));
359 if (g_variant_type_is_array (type))
361 gchar *subtype = describe_type (g_variant_type_element (type));
362 result = g_strdup_printf ("a of %s", subtype);
365 else if (g_variant_type_is_maybe (type))
367 gchar *subtype = describe_type (g_variant_type_element (type));
368 result = g_strdup_printf ("m of %s", subtype);
371 else if (g_variant_type_is_tuple (type))
373 if (!g_variant_type_equal (type, G_VARIANT_TYPE_TUPLE))
375 const GVariantType *sub;
380 string = g_string_new ("t of [");
382 length = g_variant_type_n_items (type);
383 sub = g_variant_type_first (type);
384 for (i = 0; i < length; i++)
386 gchar *subtype = describe_type (sub);
387 g_string_append (string, subtype);
390 if ((sub = g_variant_type_next (sub)))
391 g_string_append (string, ", ");
393 g_assert (sub == NULL);
394 g_string_append_c (string, ']');
396 result = g_string_free (string, FALSE);
399 result = g_strdup ("R");
401 else if (g_variant_type_is_dict_entry (type))
403 gchar *key, *value, *key2, *value2;
405 key = describe_type (g_variant_type_key (type));
406 value = describe_type (g_variant_type_value (type));
407 key2 = describe_type (g_variant_type_first (type));
408 value2 = describe_type (
409 g_variant_type_next (g_variant_type_first (type)));
410 g_assert (g_variant_type_next (g_variant_type_next (
411 g_variant_type_first (type))) == NULL);
412 g_assert_cmpstr (key, ==, key2);
413 g_assert_cmpstr (value, ==, value2);
414 result = g_strjoin ("", "e of [", key, ", ", value, "]", NULL);
420 else if (g_variant_type_equal (type, G_VARIANT_TYPE_VARIANT))
422 result = g_strdup ("V");
425 g_assert_not_reached ();
429 if (g_variant_type_is_definite (type))
431 g_assert (g_variant_type_is_basic (type));
433 if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN))
434 result = g_strdup ("b");
435 else if (g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
436 result = g_strdup ("y");
437 else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT16))
438 result = g_strdup ("n");
439 else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT16))
440 result = g_strdup ("q");
441 else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32))
442 result = g_strdup ("i");
443 else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT32))
444 result = g_strdup ("u");
445 else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT64))
446 result = g_strdup ("x");
447 else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT64))
448 result = g_strdup ("t");
449 else if (g_variant_type_equal (type, G_VARIANT_TYPE_HANDLE))
450 result = g_strdup ("h");
451 else if (g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
452 result = g_strdup ("d");
453 else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING))
454 result = g_strdup ("s");
455 else if (g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH))
456 result = g_strdup ("o");
457 else if (g_variant_type_equal (type, G_VARIANT_TYPE_SIGNATURE))
458 result = g_strdup ("g");
460 g_assert_not_reached ();
464 if (g_variant_type_equal (type, G_VARIANT_TYPE_ANY))
466 result = g_strdup ("S");
468 else if (g_variant_type_equal (type, G_VARIANT_TYPE_BASIC))
470 result = g_strdup ("?");
473 g_assert_not_reached ();
480 /* given a type string, replace one of the indefinite type characters in
481 * it with a matching type (possibly the same type).
484 generate_subtype (const gchar *type_string)
486 GVariantType *replacement;
487 GString *result, *junk;
488 gint length, n = 0, l;
490 result = g_string_new (NULL);
491 junk = g_string_new (NULL);
493 /* count the number of indefinite type characters */
494 for (length = 0; type_string[length]; length++)
495 n += type_string[length] == 'r' ||
496 type_string[length] == '?' ||
497 type_string[length] == '*';
498 /* length now is strlen (type_string) */
500 /* pick one at random to replace */
501 n = g_test_rand_int_range (0, n) + 1;
505 while (n--) l += strcspn (type_string + l + 1, "r?*") + 1;
506 g_assert (type_string[l] == 'r' ||
507 type_string[l] == '?' ||
508 type_string[l] == '*');
510 /* store up to that point in a GString */
511 g_string_append_len (result, type_string, l);
513 /* then store the replacement in the GString */
514 if (type_string[l] == 'r')
515 replacement = append_tuple_type_string (result, junk, FALSE, 3);
517 else if (type_string[l] == '?')
518 replacement = append_type_string (result, junk, FALSE, 0);
520 else if (type_string[l] == '*')
521 replacement = append_type_string (result, junk, FALSE, 3);
524 g_assert_not_reached ();
526 /* ensure the replacement has the proper type */
527 g_assert (g_variant_type_is_subtype_of (replacement,
528 (gpointer) &type_string[l]));
530 /* store the rest from the original type string */
531 g_string_append (result, type_string + l + 1);
533 g_variant_type_free (replacement);
534 g_string_free (junk, TRUE);
536 return g_string_free (result, FALSE);
541 const GVariantType *type;
542 struct typestack *parent;
545 /* given an indefinite type string, replace one of the indefinite
546 * characters in it with a matching type and ensure that the result is a
547 * subtype of the original. repeat.
550 subtype_check (const gchar *type_string,
551 struct typestack *parent_ts)
553 struct typestack ts, *node;
557 subtype = generate_subtype (type_string);
559 ts.type = G_VARIANT_TYPE (subtype);
560 ts.parent = parent_ts;
562 for (node = &ts; node; node = node->parent)
564 /* this type should be a subtype of each parent type */
565 g_assert (g_variant_type_is_subtype_of (ts.type, node->type));
567 /* it should only be a supertype when it is exactly equal */
568 g_assert (g_variant_type_is_subtype_of (node->type, ts.type) ==
569 g_variant_type_equal (ts.type, node->type));
574 if (!g_variant_type_is_definite (ts.type) && depth < 5)
576 /* the type is still indefinite and we haven't repeated too many
577 * times. go once more.
580 subtype_check (subtype, &ts);
587 test_gvarianttype (void)
591 for (i = 0; i < 2000; i++)
593 GString *type_string, *description;
594 GVariantType *type, *other_type;
595 const GVariantType *ctype;
599 type_string = g_string_new (NULL);
600 description = g_string_new (NULL);
602 /* generate a random type, its type string and a description
604 * exercises type constructor functions and g_variant_type_copy()
606 type = append_type_string (type_string, description, FALSE, 6);
608 /* convert the type string to a type and ensure that it is equal
609 * to the one produced with the type constructor routines
611 ctype = G_VARIANT_TYPE (type_string->str);
612 g_assert (g_variant_type_equal (ctype, type));
613 g_assert (g_variant_type_is_subtype_of (ctype, type));
614 g_assert (g_variant_type_is_subtype_of (type, ctype));
616 /* check if the type is indefinite */
617 if (!g_variant_type_is_definite (type))
619 struct typestack ts = { type, NULL };
621 /* if it is indefinite, then replace one of the indefinite
622 * characters with a matching type and ensure that the result
623 * is a subtype of the original type. repeat.
625 subtype_check (type_string->str, &ts);
628 /* ensure that no indefinite characters appear */
629 g_assert (strcspn (type_string->str, "r?*") == type_string->len);
632 /* describe the type.
634 * exercises the type iterator interface
636 desc = describe_type (type);
638 /* make sure the description matches */
639 g_assert_cmpstr (desc, ==, description->str);
642 /* make an invalid mutation to the type and make sure the type
643 * validation routines catch it */
644 invalid = invalid_mutation (type_string->str);
645 g_assert (g_variant_type_string_is_valid (type_string->str));
646 g_assert (!g_variant_type_string_is_valid (invalid));
649 /* concatenate another type to the type string and ensure that
650 * the result is recognised as being invalid
652 other_type = append_type_string (type_string, description, FALSE, 2);
654 g_string_free (description, TRUE);
655 g_string_free (type_string, TRUE);
656 g_variant_type_free (other_type);
657 g_variant_type_free (type);
661 #define ALIGNED(x, y) (((x + (y - 1)) / y) * y)
663 /* do our own calculation of the fixed_size and alignment of a type
664 * using a simple algorithm to make sure the "fancy" one in the
665 * implementation is correct.
668 calculate_type_info (const GVariantType *type,
672 if (g_variant_type_is_array (type) ||
673 g_variant_type_is_maybe (type))
675 calculate_type_info (g_variant_type_element (type), NULL, alignment);
680 else if (g_variant_type_is_tuple (type) ||
681 g_variant_type_is_dict_entry (type))
683 if (g_variant_type_n_items (type))
685 const GVariantType *sub;
694 sub = g_variant_type_first (type);
700 calculate_type_info (sub, &this_fs, &this_al);
702 al = MAX (al, this_al);
712 size = ALIGNED (size, this_al);
716 while ((sub = g_variant_type_next (sub)));
718 size = ALIGNED (size, al);
739 if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN) ||
740 g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
745 else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT16) ||
746 g_variant_type_equal (type, G_VARIANT_TYPE_UINT16))
751 else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32) ||
752 g_variant_type_equal (type, G_VARIANT_TYPE_UINT32) ||
753 g_variant_type_equal (type, G_VARIANT_TYPE_HANDLE))
758 else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT64) ||
759 g_variant_type_equal (type, G_VARIANT_TYPE_UINT64) ||
760 g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
764 else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING) ||
765 g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH) ||
766 g_variant_type_equal (type, G_VARIANT_TYPE_SIGNATURE))
771 else if (g_variant_type_equal (type, G_VARIANT_TYPE_VARIANT))
777 g_assert_not_reached ();
787 /* same as the describe_type() function above, but iterates over
788 * typeinfo instead of types.
791 describe_info (GVariantTypeInfo *info)
795 switch (g_variant_type_info_get_type_char (info))
797 case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
801 element = describe_info (g_variant_type_info_element (info));
802 result = g_strdup_printf ("m of %s", element);
807 case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
811 element = describe_info (g_variant_type_info_element (info));
812 result = g_strdup_printf ("a of %s", element);
817 case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
819 const gchar *sep = "";
824 string = g_string_new ("t of [");
825 length = g_variant_type_info_n_members (info);
827 for (i = 0; i < length; i++)
829 const GVariantMemberInfo *minfo;
832 g_string_append (string, sep);
835 minfo = g_variant_type_info_member_info (info, i);
836 subtype = describe_info (minfo->type_info);
837 g_string_append (string, subtype);
841 g_string_append_c (string, ']');
843 result = g_string_free (string, FALSE);
847 case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
849 const GVariantMemberInfo *keyinfo, *valueinfo;
852 g_assert_cmpint (g_variant_type_info_n_members (info), ==, 2);
853 keyinfo = g_variant_type_info_member_info (info, 0);
854 valueinfo = g_variant_type_info_member_info (info, 1);
855 key = describe_info (keyinfo->type_info);
856 value = describe_info (valueinfo->type_info);
857 result = g_strjoin ("", "e of [", key, ", ", value, "]", NULL);
863 case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
864 result = g_strdup ("V");
868 result = g_strdup (g_variant_type_info_get_type_string (info));
869 g_assert_cmpint (strlen (result), ==, 1);
876 /* check that the O(1) method of calculating offsets meshes with the
877 * results of simple iteration.
880 check_offsets (GVariantTypeInfo *info,
881 const GVariantType *type)
886 length = g_variant_type_info_n_members (info);
887 g_assert_cmpint (length, ==, g_variant_type_n_items (type));
889 /* the 'flavour' is the low order bits of the ending point of
890 * variable-size items in the tuple. this lets us test that the type
891 * info is correct for various starting alignments.
893 for (flavour = 0; flavour < 8; flavour++)
895 const GVariantType *subtype;
896 gsize last_offset_index;
901 subtype = g_variant_type_first (type);
902 last_offset_index = -1;
906 /* go through the tuple, keeping track of our position */
907 for (i = 0; i < length; i++)
912 calculate_type_info (subtype, &fixed_size, &alignment);
914 position = ALIGNED (position, alignment);
916 /* compare our current aligned position (ie: the start of this
917 * item) to the start offset that would be calculated if we
921 const GVariantMemberInfo *member;
924 member = g_variant_type_info_member_info (info, i);
925 g_assert_cmpint (member->i, ==, last_offset_index);
927 /* do the calculation using the typeinfo */
933 /* did we reach the same spot? */
934 g_assert_cmpint (start, ==, position);
939 /* fixed size. add that size. */
940 position += fixed_size;
944 /* variable size. do the flavouring. */
945 while ((position & 0x7) != flavour)
948 /* and store the offset, just like it would be in the
951 last_offset = position;
956 subtype = g_variant_type_next (subtype);
959 /* make sure we used up exactly all the types */
960 g_assert (subtype == NULL);
965 test_gvarianttypeinfo (void)
969 for (i = 0; i < 2000; i++)
971 GString *type_string, *description;
972 gsize fixed_size1, fixed_size2;
973 guint alignment1, alignment2;
974 GVariantTypeInfo *info;
978 type_string = g_string_new (NULL);
979 description = g_string_new (NULL);
982 type = append_type_string (type_string, description, TRUE, 6);
984 /* create a typeinfo for it */
985 info = g_variant_type_info_get (type);
987 /* make sure the typeinfo has the right type string */
988 g_assert_cmpstr (g_variant_type_info_get_type_string (info), ==,
991 /* calculate the alignment and fixed size, compare to the
992 * typeinfo's calculations
994 calculate_type_info (type, &fixed_size1, &alignment1);
995 g_variant_type_info_query (info, &alignment2, &fixed_size2);
996 g_assert_cmpint (fixed_size1, ==, fixed_size2);
997 g_assert_cmpint (alignment1, ==, alignment2 + 1);
999 /* test the iteration functions over typeinfo structures by
1000 * "describing" the typeinfo and verifying equality.
1002 desc = describe_info (info);
1003 g_assert_cmpstr (desc, ==, description->str);
1005 /* do extra checks for containers */
1006 if (g_variant_type_is_array (type) ||
1007 g_variant_type_is_maybe (type))
1009 const GVariantType *element;
1013 element = g_variant_type_element (type);
1014 calculate_type_info (element, &efs1, &ea1);
1015 g_variant_type_info_query_element (info, &ea2, &efs2);
1016 g_assert_cmpint (efs1, ==, efs2);
1017 g_assert_cmpint (ea1, ==, ea2 + 1);
1019 g_assert_cmpint (ea1, ==, alignment1);
1020 g_assert_cmpint (0, ==, fixed_size1);
1022 else if (g_variant_type_is_tuple (type) ||
1023 g_variant_type_is_dict_entry (type))
1025 /* make sure the "magic constants" are working */
1026 check_offsets (info, type);
1029 g_string_free (type_string, TRUE);
1030 g_string_free (description, TRUE);
1031 g_variant_type_info_unref (info);
1032 g_variant_type_free (type);
1036 g_variant_type_info_assert_no_infos ();
1039 #define MAX_FIXED_MULTIPLIER 256
1040 #define MAX_INSTANCE_SIZE 1024
1041 #define MAX_ARRAY_CHILDREN 128
1042 #define MAX_TUPLE_CHILDREN 128
1044 /* this function generates a random type such that all characteristics
1045 * that are "interesting" to the serialiser are tested.
1047 * this basically means:
1048 * - test different alignments
1049 * - test variable sized items and fixed sized items
1050 * - test different fixed sizes
1053 random_type_string (void)
1055 const guchar base_types[] = "ynix";
1058 base_type = base_types[g_test_rand_int_range (0, 4)];
1060 if (g_test_rand_bit ())
1061 /* construct a fixed-sized type */
1063 char type_string[MAX_FIXED_MULTIPLIER];
1067 multiplier = g_test_rand_int_range (1, sizeof type_string - 1);
1069 type_string[i++] = '(';
1070 while (multiplier--)
1071 type_string[i++] = base_type;
1072 type_string[i++] = ')';
1074 return g_strndup (type_string, i);
1077 /* construct a variable-sized type */
1079 char type_string[2] = { 'a', base_type };
1081 return g_strndup (type_string, 2);
1087 GVariantTypeInfo *type_info;
1090 gboolean is_fixed_sized;
1094 #define INSTANCE_MAGIC 1287582829
1098 static RandomInstance *
1099 random_instance (GVariantTypeInfo *type_info)
1101 RandomInstance *instance;
1103 instance = g_slice_new (RandomInstance);
1105 if (type_info == NULL)
1107 gchar *str = random_type_string ();
1108 instance->type_info = g_variant_type_info_get (G_VARIANT_TYPE (str));
1112 instance->type_info = g_variant_type_info_ref (type_info);
1114 instance->seed = g_test_rand_int ();
1116 g_variant_type_info_query (instance->type_info,
1117 &instance->alignment,
1120 instance->is_fixed_sized = instance->size != 0;
1122 if (!instance->is_fixed_sized)
1123 instance->size = g_test_rand_int_range (0, MAX_INSTANCE_SIZE);
1125 instance->magic = INSTANCE_MAGIC;
1131 random_instance_free (RandomInstance *instance)
1133 g_variant_type_info_unref (instance->type_info);
1134 g_slice_free (RandomInstance, instance);
1138 append_instance_size (RandomInstance *instance,
1141 *offset += (-*offset) & instance->alignment;
1142 *offset += instance->size;
1146 random_instance_write (RandomInstance *instance,
1152 g_assert_cmpint ((gsize) buffer & ALIGN_BITS & instance->alignment, ==, 0);
1154 rand = g_rand_new_with_seed (instance->seed);
1155 for (i = 0; i < instance->size; i++)
1156 buffer[i] = g_rand_int (rand);
1161 append_instance_data (RandomInstance *instance,
1164 while (((gsize) *buffer) & instance->alignment)
1165 *(*buffer)++ = '\0';
1167 random_instance_write (instance, *buffer);
1168 *buffer += instance->size;
1172 random_instance_assert (RandomInstance *instance,
1179 g_assert_cmpint ((gsize) buffer & ALIGN_BITS & instance->alignment, ==, 0);
1180 g_assert_cmpint (size, ==, instance->size);
1182 rand = g_rand_new_with_seed (instance->seed);
1183 for (i = 0; i < instance->size; i++)
1185 guchar byte = g_rand_int (rand);
1187 g_assert (buffer[i] == byte);
1191 return i == instance->size;
1195 random_instance_check (RandomInstance *instance,
1202 g_assert_cmpint ((gsize) buffer & ALIGN_BITS & instance->alignment, ==, 0);
1204 if (size != instance->size)
1207 rand = g_rand_new_with_seed (instance->seed);
1208 for (i = 0; i < instance->size; i++)
1209 if (buffer[i] != (guchar) g_rand_int (rand))
1213 return i == instance->size;
1217 random_instance_filler (GVariantSerialised *serialised,
1220 RandomInstance *instance = data;
1222 g_assert (instance->magic == INSTANCE_MAGIC);
1224 if (serialised->type_info == NULL)
1225 serialised->type_info = instance->type_info;
1227 if (serialised->size == 0)
1228 serialised->size = instance->size;
1230 g_assert (serialised->type_info == instance->type_info);
1231 g_assert (serialised->size == instance->size);
1233 if (serialised->data)
1234 random_instance_write (instance, serialised->data);
1238 calculate_offset_size (gsize body_size,
1244 if (body_size + n_offsets <= G_MAXUINT8)
1247 if (body_size + 2 * n_offsets <= G_MAXUINT16)
1250 if (body_size + 4 * n_offsets <= G_MAXUINT32)
1253 /* the test case won't generate anything bigger */
1254 g_assert_not_reached ();
1258 flavoured_malloc (gsize size, gsize flavour)
1260 g_assert (flavour < 8);
1265 return ((gchar *) g_malloc (size + flavour)) + flavour;
1269 flavoured_free (gpointer data,
1272 g_free (((gchar *) data) - flavour);
1276 append_offset (guchar **offset_ptr,
1282 guchar bytes[sizeof (gsize)];
1286 tmpvalue.integer = GSIZE_TO_LE (offset);
1287 memcpy (*offset_ptr, tmpvalue.bytes, offset_size);
1288 *offset_ptr += offset_size;
1292 prepend_offset (guchar **offset_ptr,
1298 guchar bytes[sizeof (gsize)];
1302 *offset_ptr -= offset_size;
1303 tmpvalue.integer = GSIZE_TO_LE (offset);
1304 memcpy (*offset_ptr, tmpvalue.bytes, offset_size);
1310 GVariantTypeInfo *type_info;
1311 RandomInstance *instance;
1315 instance = random_instance (NULL);
1318 const gchar *element;
1321 element = g_variant_type_info_get_type_string (instance->type_info);
1322 tmp = g_strdup_printf ("m%s", element);
1323 type_info = g_variant_type_info_get (G_VARIANT_TYPE (tmp));
1327 needed_size = g_variant_serialiser_needed_size (type_info,
1328 random_instance_filler,
1330 g_assert_cmpint (needed_size, ==, 0);
1332 needed_size = g_variant_serialiser_needed_size (type_info,
1333 random_instance_filler,
1334 (gpointer *) &instance, 1);
1336 if (instance->is_fixed_sized)
1337 g_assert_cmpint (needed_size, ==, instance->size);
1339 g_assert_cmpint (needed_size, ==, instance->size + 1);
1344 ptr = data = g_malloc (needed_size);
1345 append_instance_data (instance, &ptr);
1347 if (!instance->is_fixed_sized)
1350 g_assert_cmpint (ptr - data, ==, needed_size);
1357 alignment = (instance->alignment & ALIGN_BITS) + 1;
1359 for (flavour = 0; flavour < 8; flavour += alignment)
1361 GVariantSerialised serialised;
1362 GVariantSerialised child;
1364 serialised.type_info = type_info;
1365 serialised.data = flavoured_malloc (needed_size, flavour);
1366 serialised.size = needed_size;
1368 g_variant_serialiser_serialise (serialised,
1369 random_instance_filler,
1370 (gpointer *) &instance, 1);
1371 child = g_variant_serialised_get_child (serialised, 0);
1372 g_assert (child.type_info == instance->type_info);
1373 random_instance_assert (instance, child.data, child.size);
1374 g_variant_type_info_unref (child.type_info);
1375 flavoured_free (serialised.data, flavour);
1379 g_variant_type_info_unref (type_info);
1380 random_instance_free (instance);
1389 for (i = 0; i < 1000; i++)
1392 g_variant_type_info_assert_no_infos ();
1398 GVariantTypeInfo *element_info;
1399 GVariantTypeInfo *array_info;
1400 RandomInstance **instances;
1407 gchar *element_type, *array_type;
1409 element_type = random_type_string ();
1410 array_type = g_strdup_printf ("a%s", element_type);
1412 element_info = g_variant_type_info_get (G_VARIANT_TYPE (element_type));
1413 array_info = g_variant_type_info_get (G_VARIANT_TYPE (array_type));
1414 g_assert (g_variant_type_info_element (array_info) == element_info);
1416 g_free (element_type);
1417 g_free (array_type);
1423 n_children = g_test_rand_int_range (0, MAX_ARRAY_CHILDREN);
1424 instances = g_new (RandomInstance *, n_children);
1425 for (i = 0; i < n_children; i++)
1426 instances[i] = random_instance (element_info);
1429 needed_size = g_variant_serialiser_needed_size (array_info,
1430 random_instance_filler,
1431 (gpointer *) instances,
1435 gsize element_fixed_size;
1436 gsize body_size = 0;
1439 for (i = 0; i < n_children; i++)
1440 append_instance_size (instances[i], &body_size);
1442 g_variant_type_info_query (element_info, NULL, &element_fixed_size);
1444 if (!element_fixed_size)
1446 offset_size = calculate_offset_size (body_size, n_children);
1448 if (offset_size == 0)
1454 g_assert_cmpint (needed_size, ==, body_size + n_children * offset_size);
1458 guchar *offset_ptr, *body_ptr;
1461 body_ptr = data = g_malloc (needed_size);
1462 offset_ptr = body_ptr + needed_size - offset_size * n_children;
1464 for (i = 0; i < n_children; i++)
1466 append_instance_data (instances[i], &body_ptr);
1467 append_offset (&offset_ptr, body_ptr - data, offset_size);
1470 g_assert (body_ptr == data + needed_size - offset_size * n_children);
1471 g_assert (offset_ptr == data + needed_size);
1479 g_variant_type_info_query (array_info, &alignment, NULL);
1480 alignment = (alignment & ALIGN_BITS) + 1;
1482 for (flavour = 0; flavour < 8; flavour += alignment)
1484 GVariantSerialised serialised;
1486 serialised.type_info = array_info;
1487 serialised.data = flavoured_malloc (needed_size, flavour);
1488 serialised.size = needed_size;
1490 g_variant_serialiser_serialise (serialised, random_instance_filler,
1491 (gpointer *) instances, n_children);
1493 g_assert (memcmp (serialised.data, data, serialised.size) == 0);
1494 g_assert (g_variant_serialised_n_children (serialised) == n_children);
1496 for (i = 0; i < n_children; i++)
1498 GVariantSerialised child;
1500 child = g_variant_serialised_get_child (serialised, i);
1501 g_assert (child.type_info == instances[i]->type_info);
1502 random_instance_assert (instances[i], child.data, child.size);
1503 g_variant_type_info_unref (child.type_info);
1506 flavoured_free (serialised.data, flavour);
1513 for (i = 0; i < n_children; i++)
1514 random_instance_free (instances[i]);
1518 g_variant_type_info_unref (element_info);
1519 g_variant_type_info_unref (array_info);
1528 for (i = 0; i < 100; i++)
1531 g_variant_type_info_assert_no_infos ();
1537 GVariantTypeInfo *type_info;
1538 RandomInstance **instances;
1539 gboolean fixed_size;
1546 n_children = g_test_rand_int_range (0, MAX_TUPLE_CHILDREN);
1547 instances = g_new (RandomInstance *, n_children);
1550 GString *type_string;
1556 type_string = g_string_new ("(");
1557 for (i = 0; i < n_children; i++)
1561 instances[i] = random_instance (NULL);
1563 alignment |= instances[i]->alignment;
1564 if (!instances[i]->is_fixed_sized)
1567 str = g_variant_type_info_get_type_string (instances[i]->type_info);
1568 g_string_append (type_string, str);
1570 g_string_append_c (type_string, ')');
1572 type_info = g_variant_type_info_get (G_VARIANT_TYPE (type_string->str));
1573 g_string_free (type_string, TRUE);
1576 needed_size = g_variant_serialiser_needed_size (type_info,
1577 random_instance_filler,
1578 (gpointer *) instances,
1581 gsize body_size = 0;
1585 for (i = 0; i < n_children; i++)
1587 append_instance_size (instances[i], &body_size);
1589 if (i != n_children - 1 && !instances[i]->is_fixed_sized)
1595 body_size += (-body_size) & alignment;
1597 g_assert ((body_size == 0) == (n_children == 0));
1598 if (n_children == 0)
1602 offset_size = calculate_offset_size (body_size, offsets);
1603 g_assert_cmpint (needed_size, ==, body_size + offsets * offset_size);
1611 body_ptr = data = g_malloc (needed_size);
1612 ofs_ptr = body_ptr + needed_size;
1614 for (i = 0; i < n_children; i++)
1616 append_instance_data (instances[i], &body_ptr);
1618 if (i != n_children - 1 && !instances[i]->is_fixed_sized)
1619 prepend_offset (&ofs_ptr, body_ptr - data, offset_size);
1624 while (((gsize) body_ptr) & alignment)
1627 g_assert ((body_ptr == data) == (n_children == 0));
1628 if (n_children == 0)
1634 g_assert (body_ptr == ofs_ptr);
1641 alignment = (alignment & ALIGN_BITS) + 1;
1643 for (flavour = 0; flavour < 8; flavour += alignment)
1645 GVariantSerialised serialised;
1647 serialised.type_info = type_info;
1648 serialised.data = flavoured_malloc (needed_size, flavour);
1649 serialised.size = needed_size;
1651 g_variant_serialiser_serialise (serialised, random_instance_filler,
1652 (gpointer *) instances, n_children);
1654 g_assert (memcmp (serialised.data, data, serialised.size) == 0);
1655 g_assert (g_variant_serialised_n_children (serialised) == n_children);
1657 for (i = 0; i < n_children; i++)
1659 GVariantSerialised child;
1661 child = g_variant_serialised_get_child (serialised, i);
1662 g_assert (child.type_info == instances[i]->type_info);
1663 random_instance_assert (instances[i], child.data, child.size);
1664 g_variant_type_info_unref (child.type_info);
1667 flavoured_free (serialised.data, flavour);
1674 for (i = 0; i < n_children; i++)
1675 random_instance_free (instances[i]);
1679 g_variant_type_info_unref (type_info);
1688 for (i = 0; i < 100; i++)
1691 g_variant_type_info_assert_no_infos ();
1697 GVariantTypeInfo *type_info;
1698 RandomInstance *instance;
1699 const gchar *type_string;
1704 type_info = g_variant_type_info_get (G_VARIANT_TYPE_VARIANT);
1705 instance = random_instance (NULL);
1707 type_string = g_variant_type_info_get_type_string (instance->type_info);
1708 len = strlen (type_string);
1710 needed_size = g_variant_serialiser_needed_size (type_info,
1711 random_instance_filler,
1712 (gpointer *) &instance, 1);
1714 g_assert_cmpint (needed_size, ==, instance->size + 1 + len);
1719 ptr = data = g_malloc (needed_size);
1720 append_instance_data (instance, &ptr);
1722 memcpy (ptr, type_string, len);
1725 g_assert (data + needed_size == ptr);
1732 /* variants are always 8-aligned */
1733 alignment = ALIGN_BITS + 1;
1735 for (flavour = 0; flavour < 8; flavour += alignment)
1737 GVariantSerialised serialised;
1738 GVariantSerialised child;
1740 serialised.type_info = type_info;
1741 serialised.data = flavoured_malloc (needed_size, flavour);
1742 serialised.size = needed_size;
1744 g_variant_serialiser_serialise (serialised, random_instance_filler,
1745 (gpointer *) &instance, 1);
1747 g_assert (memcmp (serialised.data, data, serialised.size) == 0);
1748 g_assert (g_variant_serialised_n_children (serialised) == 1);
1750 child = g_variant_serialised_get_child (serialised, 0);
1751 g_assert (child.type_info == instance->type_info);
1752 random_instance_check (instance, child.data, child.size);
1754 g_variant_type_info_unref (child.type_info);
1755 flavoured_free (serialised.data, flavour);
1759 g_variant_type_info_unref (type_info);
1760 random_instance_free (instance);
1765 test_variants (void)
1769 for (i = 0; i < 100; i++)
1772 g_variant_type_info_assert_no_infos ();
1785 #define is_objpath is_string | 2
1786 #define is_sig is_string | 4
1788 { is_nval, 0, NULL },
1789 { is_nval, 13, "hello\xffworld!" },
1790 { is_string, 13, "hello world!" },
1791 { is_nval, 13, "hello world\0" },
1792 { is_nval, 13, "hello\0world!" },
1793 { is_nval, 12, "hello world!" },
1795 { is_objpath, 2, "/" },
1796 { is_objpath, 3, "/a" },
1797 { is_string, 3, "//" },
1798 { is_objpath, 11, "/some/path" },
1799 { is_string, 12, "/some/path/" },
1800 { is_nval, 11, "/some\0path" },
1801 { is_string, 11, "/some\\path" },
1802 { is_string, 12, "/some//path" },
1803 { is_string, 12, "/some-/path" },
1807 { is_sig, 5, "(si)" },
1808 { is_string, 4, "(si" },
1809 { is_string, 2, "*" },
1810 { is_sig, 3, "ai" },
1811 { is_string, 3, "mi" },
1812 { is_string, 2, "r" },
1813 { is_sig, 15, "(yyy{sv}ssiai)" },
1814 { is_string, 16, "(yyy{yv}ssiai))" },
1815 { is_string, 15, "(yyy{vv}ssiai)" },
1816 { is_string, 15, "(yyy{sv)ssiai}" }
1820 for (i = 0; i < G_N_ELEMENTS (test_cases); i++)
1824 flags = g_variant_serialiser_is_string (test_cases[i].data,
1828 flags |= g_variant_serialiser_is_object_path (test_cases[i].data,
1832 flags |= g_variant_serialiser_is_signature (test_cases[i].data,
1836 g_assert (flags == test_cases[i].flags);
1840 typedef struct _TreeInstance TreeInstance;
1841 struct _TreeInstance
1843 GVariantTypeInfo *info;
1845 TreeInstance **children;
1856 static GVariantType *
1857 make_random_definite_type (int depth)
1859 GString *description;
1860 GString *type_string;
1863 description = g_string_new (NULL);
1864 type_string = g_string_new (NULL);
1865 type = append_type_string (type_string, description, TRUE, depth);
1866 g_string_free (description, TRUE);
1867 g_string_free (type_string, TRUE);
1873 make_random_string (gchar *string,
1875 const GVariantType *type)
1879 /* create strings that are valid signature strings */
1880 #define good_chars "bynqiuxthdsog"
1882 for (i = 0; i < size - 1; i++)
1883 string[i] = good_chars[g_test_rand_int_range (0, strlen (good_chars))];
1886 /* in case we need an object path, prefix a '/' */
1887 if (*g_variant_type_peek_string (type) == 'o')
1893 static TreeInstance *
1894 tree_instance_new (const GVariantType *type,
1897 const GVariantType *child_type = NULL;
1898 GVariantType *mytype = NULL;
1899 TreeInstance *instance;
1900 gboolean is_tuple_type;
1903 type = mytype = make_random_definite_type (depth);
1905 instance = g_slice_new (TreeInstance);
1906 instance->info = g_variant_type_info_get (type);
1907 instance->children = NULL;
1908 instance->n_children = 0;
1909 instance->data_size = 0;
1911 is_tuple_type = FALSE;
1913 switch (*g_variant_type_peek_string (type))
1915 case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
1916 instance->n_children = g_test_rand_int_range (0, 2);
1917 child_type = g_variant_type_element (type);
1920 case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
1921 instance->n_children = g_test_rand_int_range (0, MAX_ARRAY_CHILDREN);
1922 child_type = g_variant_type_element (type);
1925 case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
1926 case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
1927 instance->n_children = g_variant_type_n_items (type);
1928 child_type = g_variant_type_first (type);
1929 is_tuple_type = TRUE;
1932 case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
1933 instance->n_children = 1;
1938 instance->data.integer = g_test_rand_int_range (0, 2);
1939 instance->data_size = 1;
1943 instance->data.integer = g_test_rand_int ();
1944 instance->data_size = 1;
1948 instance->data.integer = g_test_rand_int ();
1949 instance->data_size = 2;
1952 case 'i': case 'u': case 'h':
1953 instance->data.integer = g_test_rand_int ();
1954 instance->data_size = 4;
1958 instance->data.integer = g_test_rand_int ();
1959 instance->data.integer <<= 32;
1960 instance->data.integer |= (guint32) g_test_rand_int ();
1961 instance->data_size = 8;
1965 instance->data.floating = g_test_rand_double ();
1966 instance->data_size = 8;
1969 case 's': case 'o': case 'g':
1970 instance->data_size = g_test_rand_int_range (10, 20);
1971 make_random_string (instance->data.string, instance->data_size, type);
1975 if (instance->data_size == 0)
1976 /* no data -> it is a container */
1980 instance->children = g_new (TreeInstance *, instance->n_children);
1982 for (i = 0; i < instance->n_children; i++)
1984 instance->children[i] = tree_instance_new (child_type, depth - 1);
1987 child_type = g_variant_type_next (child_type);
1990 g_assert (!is_tuple_type || child_type == NULL);
1993 g_variant_type_free (mytype);
1999 tree_instance_free (TreeInstance *instance)
2003 g_variant_type_info_unref (instance->info);
2004 for (i = 0; i < instance->n_children; i++)
2005 tree_instance_free (instance->children[i]);
2006 g_free (instance->children);
2007 g_slice_free (TreeInstance, instance);
2010 static gboolean i_am_writing_byteswapped;
2013 tree_filler (GVariantSerialised *serialised,
2016 TreeInstance *instance = data;
2018 if (serialised->type_info == NULL)
2019 serialised->type_info = instance->info;
2021 if (instance->data_size == 0)
2022 /* is a container */
2024 if (serialised->size == 0)
2026 g_variant_serialiser_needed_size (instance->info, tree_filler,
2027 (gpointer *) instance->children,
2028 instance->n_children);
2030 if (serialised->data)
2031 g_variant_serialiser_serialise (*serialised, tree_filler,
2032 (gpointer *) instance->children,
2033 instance->n_children);
2038 if (serialised->size == 0)
2039 serialised->size = instance->data_size;
2041 if (serialised->data)
2043 switch (instance->data_size)
2046 *serialised->data = instance->data.integer;
2051 guint16 value = instance->data.integer;
2053 if (i_am_writing_byteswapped)
2054 value = GUINT16_SWAP_LE_BE (value);
2056 *(guint16 *) serialised->data = value;
2062 guint32 value = instance->data.integer;
2064 if (i_am_writing_byteswapped)
2065 value = GUINT32_SWAP_LE_BE (value);
2067 *(guint32 *) serialised->data = value;
2073 guint64 value = instance->data.integer;
2075 if (i_am_writing_byteswapped)
2076 value = GUINT64_SWAP_LE_BE (value);
2078 *(guint64 *) serialised->data = value;
2083 memcpy (serialised->data,
2084 instance->data.string,
2085 instance->data_size);
2093 check_tree (TreeInstance *instance,
2094 GVariantSerialised serialised)
2096 if (instance->info != serialised.type_info)
2099 if (instance->data_size == 0)
2100 /* is a container */
2104 if (g_variant_serialised_n_children (serialised) !=
2105 instance->n_children)
2108 for (i = 0; i < instance->n_children; i++)
2110 GVariantSerialised child;
2111 gpointer data = NULL;
2114 child = g_variant_serialised_get_child (serialised, i);
2115 if (child.size && child.data == NULL)
2116 child.data = data = g_malloc0 (child.size);
2117 ok = check_tree (instance->children[i], child);
2118 g_variant_type_info_unref (child.type_info);
2130 switch (instance->data_size)
2133 g_assert (serialised.size == 1);
2134 return *(guint8 *) serialised.data ==
2135 (guint8) instance->data.integer;
2138 g_assert (serialised.size == 2);
2139 return *(guint16 *) serialised.data ==
2140 (guint16) instance->data.integer;
2143 g_assert (serialised.size == 4);
2144 return *(guint32 *) serialised.data ==
2145 (guint32) instance->data.integer;
2148 g_assert (serialised.size == 8);
2149 return *(guint64 *) serialised.data ==
2150 (guint64) instance->data.integer;
2153 if (serialised.size != instance->data_size)
2156 return memcmp (serialised.data,
2157 instance->data.string,
2158 instance->data_size) == 0;
2164 serialise_tree (TreeInstance *tree,
2165 GVariantSerialised *serialised)
2167 GVariantSerialised empty = { };
2169 *serialised = empty;
2170 tree_filler (serialised, tree);
2171 serialised->data = g_malloc (serialised->size);
2172 tree_filler (serialised, tree);
2176 test_byteswap (void)
2178 GVariantSerialised one, two;
2181 tree = tree_instance_new (NULL, 3);
2182 serialise_tree (tree, &one);
2184 i_am_writing_byteswapped = TRUE;
2185 serialise_tree (tree, &two);
2186 i_am_writing_byteswapped = FALSE;
2188 g_variant_serialised_byteswap (two);
2190 g_assert_cmpint (one.size, ==, two.size);
2191 g_assert (memcmp (one.data, two.data, one.size) == 0);
2193 tree_instance_free (tree);
2199 test_byteswaps (void)
2203 for (i = 0; i < 200; i++)
2206 g_variant_type_info_assert_no_infos ();
2210 test_fuzz (gdouble *fuzziness)
2212 GVariantSerialised serialised;
2215 /* make an instance */
2216 tree = tree_instance_new (NULL, 3);
2219 serialise_tree (tree, &serialised);
2221 g_assert (g_variant_serialised_is_normal (serialised));
2222 g_assert (check_tree (tree, serialised));
2224 if (serialised.size)
2226 gboolean fuzzed = FALSE;
2233 for (i = 0; i < serialised.size; i++)
2234 if (randomly (*fuzziness))
2236 serialised.data[i] += g_test_rand_int_range (1, 256);
2241 /* at least one byte in the serialised data has changed.
2243 * this means that at least one of the following is true:
2245 * - the serialised data now represents a different value:
2246 * check_tree() will return FALSE
2248 * - the serialised data is in non-normal form:
2249 * g_variant_serialiser_is_normal() will return FALSE
2251 * we always do both checks to increase exposure of the serialiser
2254 a = g_variant_serialised_is_normal (serialised);
2255 b = check_tree (tree, serialised);
2257 g_assert (!a || !b);
2260 tree_instance_free (tree);
2261 g_free (serialised.data);
2266 test_fuzzes (gpointer data)
2271 fuzziness = GPOINTER_TO_INT (data) / 100.;
2273 for (i = 0; i < 200; i++)
2274 test_fuzz (&fuzziness);
2276 g_variant_type_info_assert_no_infos ();
2280 tree_instance_get_gvariant (TreeInstance *tree)
2282 const GVariantType *type;
2285 type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
2287 switch (g_variant_type_info_get_type_char (tree->info))
2289 case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
2291 const GVariantType *child_type;
2294 if (tree->n_children)
2295 child = tree_instance_get_gvariant (tree->children[0]);
2299 child_type = g_variant_type_element (type);
2301 if (child != NULL && randomly (0.5))
2304 result = g_variant_new_maybe (child_type, child);
2308 case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
2310 const GVariantType *child_type;
2311 GVariant **children;
2314 children = g_new (GVariant *, tree->n_children);
2315 for (i = 0; i < tree->n_children; i++)
2316 children[i] = tree_instance_get_gvariant (tree->children[i]);
2318 child_type = g_variant_type_element (type);
2320 if (i > 0 && randomly (0.5))
2323 result = g_variant_new_array (child_type, children, tree->n_children);
2328 case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
2330 GVariant **children;
2333 children = g_new (GVariant *, tree->n_children);
2334 for (i = 0; i < tree->n_children; i++)
2335 children[i] = tree_instance_get_gvariant (tree->children[i]);
2337 result = g_variant_new_tuple (children, tree->n_children);
2342 case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
2344 GVariant *key, *val;
2346 g_assert (tree->n_children == 2);
2348 key = tree_instance_get_gvariant (tree->children[0]);
2349 val = tree_instance_get_gvariant (tree->children[1]);
2351 result = g_variant_new_dict_entry (key, val);
2355 case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
2359 g_assert (tree->n_children == 1);
2361 value = tree_instance_get_gvariant (tree->children[0]);
2362 result = g_variant_new_variant (value);
2367 result = g_variant_new_boolean (tree->data.integer > 0);
2371 result = g_variant_new_byte (tree->data.integer);
2375 result = g_variant_new_int16 (tree->data.integer);
2379 result = g_variant_new_uint16 (tree->data.integer);
2383 result = g_variant_new_int32 (tree->data.integer);
2387 result = g_variant_new_uint32 (tree->data.integer);
2391 result = g_variant_new_int64 (tree->data.integer);
2395 result = g_variant_new_uint64 (tree->data.integer);
2399 result = g_variant_new_handle (tree->data.integer);
2403 result = g_variant_new_double (tree->data.floating);
2407 result = g_variant_new_string (tree->data.string);
2411 result = g_variant_new_object_path (tree->data.string);
2415 result = g_variant_new_signature (tree->data.string);
2419 g_assert_not_reached ();
2426 tree_instance_check_gvariant (TreeInstance *tree,
2429 const GVariantType *type;
2431 type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
2432 g_assert (g_variant_is_of_type (value, type));
2434 switch (g_variant_type_info_get_type_char (tree->info))
2436 case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
2441 child = g_variant_get_maybe (value);
2443 if (child != NULL && tree->n_children == 1)
2444 equal = tree_instance_check_gvariant (tree->children[0], child);
2445 else if (child == NULL && tree->n_children == 0)
2451 g_variant_unref (child);
2457 case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
2458 case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
2459 case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
2463 if (g_variant_n_children (value) != tree->n_children)
2466 for (i = 0; i < tree->n_children; i++)
2471 child = g_variant_get_child_value (value, i);
2472 equal = tree_instance_check_gvariant (tree->children[i], child);
2473 g_variant_unref (child);
2483 case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
2485 const gchar *str1, *str2;
2489 child = g_variant_get_variant (value);
2490 str1 = g_variant_get_type_string (child);
2491 str2 = g_variant_type_info_get_type_string (tree->children[0]->info);
2492 /* GVariant only keeps one copy of type strings around */
2493 equal = str1 == str2 &&
2494 tree_instance_check_gvariant (tree->children[0], child);
2496 g_variant_unref (child);
2503 return g_variant_get_boolean (value) == tree->data.integer;
2506 return g_variant_get_byte (value) == (guchar) tree->data.integer;
2509 return g_variant_get_int16 (value) == (gint16) tree->data.integer;
2512 return g_variant_get_uint16 (value) == (guint16) tree->data.integer;
2515 return g_variant_get_int32 (value) == (gint32) tree->data.integer;
2518 return g_variant_get_uint32 (value) == (guint32) tree->data.integer;
2521 return g_variant_get_int64 (value) == (gint64) tree->data.integer;
2524 return g_variant_get_uint64 (value) == (guint64) tree->data.integer;
2527 return g_variant_get_handle (value) == (gint32) tree->data.integer;
2531 gdouble floating = g_variant_get_double (value);
2533 return memcmp (&floating, &tree->data.floating, sizeof floating) == 0;
2539 return strcmp (g_variant_get_string (value, NULL),
2540 tree->data.string) == 0;
2543 g_assert_not_reached ();
2548 tree_instance_build_gvariant (TreeInstance *tree,
2549 GVariantBuilder *builder,
2552 const GVariantType *type;
2554 type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
2556 if (g_variant_type_is_container (type))
2560 /* force GVariantBuilder to guess the type half the time */
2561 if (guess_ok && randomly (0.5))
2563 if (g_variant_type_is_array (type) && tree->n_children)
2564 type = G_VARIANT_TYPE_ARRAY;
2566 if (g_variant_type_is_maybe (type) && tree->n_children)
2567 type = G_VARIANT_TYPE_MAYBE;
2569 if (g_variant_type_is_tuple (type))
2570 type = G_VARIANT_TYPE_TUPLE;
2572 if (g_variant_type_is_dict_entry (type))
2573 type = G_VARIANT_TYPE_DICT_ENTRY;
2578 g_variant_builder_open (builder, type);
2580 for (i = 0; i < tree->n_children; i++)
2581 tree_instance_build_gvariant (tree->children[i], builder, guess_ok);
2583 g_variant_builder_close (builder);
2586 g_variant_builder_add_value (builder, tree_instance_get_gvariant (tree));
2591 tree_instance_check_iter (TreeInstance *tree,
2596 value = g_variant_iter_next_value (iter);
2598 if (g_variant_is_container (value))
2602 iter = g_variant_iter_new (value);
2603 g_variant_unref (value);
2605 if (g_variant_iter_n_children (iter) != tree->n_children)
2607 g_variant_iter_free (iter);
2611 for (i = 0; i < tree->n_children; i++)
2612 if (!tree_instance_check_iter (tree->children[i], iter))
2614 g_variant_iter_free (iter);
2618 g_assert (g_variant_iter_next_value (iter) == NULL);
2619 g_variant_iter_free (iter);
2628 equal = tree_instance_check_gvariant (tree, value);
2629 g_variant_unref (value);
2636 test_container (void)
2642 tree = tree_instance_new (NULL, 3);
2643 value = g_variant_ref_sink (tree_instance_get_gvariant (tree));
2645 s1 = g_variant_print (value, TRUE);
2646 g_assert (tree_instance_check_gvariant (tree, value));
2648 g_variant_get_data (value);
2650 s2 = g_variant_print (value, TRUE);
2651 g_assert (tree_instance_check_gvariant (tree, value));
2653 g_assert_cmpstr (s1, ==, s2);
2655 if (g_variant_is_container (value))
2657 GVariantBuilder builder;
2663 g_variant_builder_init (&builder, G_VARIANT_TYPE_VARIANT);
2664 tree_instance_build_gvariant (tree, &builder, TRUE);
2665 built = g_variant_builder_end (&builder);
2666 g_variant_ref_sink (built);
2667 g_variant_get_data (built);
2668 val = g_variant_get_variant (built);
2670 s3 = g_variant_print (val, TRUE);
2671 g_assert_cmpstr (s1, ==, s3);
2673 g_variant_iter_init (&iter, built);
2674 g_assert (tree_instance_check_iter (tree, &iter));
2675 g_assert (g_variant_iter_next_value (&iter) == NULL);
2677 g_variant_unref (built);
2678 g_variant_unref (val);
2682 tree_instance_free (tree);
2683 g_variant_unref (value);
2691 const gchar invalid[] = "hello\xffworld";
2694 /* ensure that the test data is not valid utf8... */
2695 g_assert (!g_utf8_validate (invalid, -1, NULL));
2697 /* load the data untrusted */
2698 value = g_variant_new_from_data (G_VARIANT_TYPE_STRING,
2699 invalid, sizeof invalid,
2702 /* ensure that the problem is caught and we get valid UTF-8 */
2703 g_assert (g_utf8_validate (g_variant_get_string (value, NULL), -1, NULL));
2704 g_variant_unref (value);
2707 /* now load it trusted */
2708 value = g_variant_new_from_data (G_VARIANT_TYPE_STRING,
2709 invalid, sizeof invalid,
2712 /* ensure we get the invalid data (ie: make sure that time wasn't
2713 * wasted on validating data that was marked as trusted)
2715 g_assert (g_variant_get_string (value, NULL) == invalid);
2716 g_variant_unref (value);
2720 test_containers (void)
2724 for (i = 0; i < 100; i++)
2729 g_variant_type_info_assert_no_infos ();
2733 test_format_strings (void)
2738 g_assert (g_variant_format_string_scan ("i", NULL, &end) && *end == '\0');
2739 g_assert (g_variant_format_string_scan ("@i", NULL, &end) && *end == '\0');
2740 g_assert (g_variant_format_string_scan ("@ii", NULL, &end) && *end == 'i');
2741 g_assert (g_variant_format_string_scan ("^a&s", NULL, &end) && *end == '\0');
2742 g_assert (g_variant_format_string_scan ("(^as)", NULL, &end) &&
2744 g_assert (!g_variant_format_string_scan ("(^s)", NULL, &end));
2745 g_assert (!g_variant_format_string_scan ("(^a)", NULL, &end));
2746 g_assert (!g_variant_format_string_scan ("(z)", NULL, &end));
2747 g_assert (!g_variant_format_string_scan ("az", NULL, &end));
2748 g_assert (!g_variant_format_string_scan ("{**}", NULL, &end));
2749 g_assert (!g_variant_format_string_scan ("{@**}", NULL, &end));
2750 g_assert (g_variant_format_string_scan ("{@y*}", NULL, &end) &&
2752 g_assert (g_variant_format_string_scan ("{yv}", NULL, &end) &&
2754 g_assert (!g_variant_format_string_scan ("{&?v}", NULL, &end));
2755 g_assert (g_variant_format_string_scan ("{@?v}", NULL, &end) &&
2757 g_assert (!g_variant_format_string_scan ("{&@sv}", NULL, &end));
2758 g_assert (!g_variant_format_string_scan ("{@&sv}", NULL, &end));
2759 g_assert (g_variant_format_string_scan ("{&sv}", NULL, &end) &&
2761 g_assert (!g_variant_format_string_scan ("{vv}", NULL, &end));
2762 g_assert (!g_variant_format_string_scan ("{y}", NULL, &end));
2763 g_assert (!g_variant_format_string_scan ("{yyy}", NULL, &end));
2764 g_assert (!g_variant_format_string_scan ("{ya}", NULL, &end));
2765 g_assert (g_variant_format_string_scan ("&s", NULL, &end) && *end == '\0');
2766 g_assert (!g_variant_format_string_scan ("&as", NULL, &end));
2767 g_assert (!g_variant_format_string_scan ("@z", NULL, &end));
2768 g_assert (!g_variant_format_string_scan ("az", NULL, &end));
2769 g_assert (!g_variant_format_string_scan ("a&s", NULL, &end));
2771 type = g_variant_format_string_scan_type ("mm(@xy^a&s*?@?)", NULL, &end);
2772 g_assert (type && *end == '\0');
2773 g_assert (g_variant_type_equal (type, G_VARIANT_TYPE ("mm(xyas*?\?)")));
2774 g_variant_type_free (type);
2776 type = g_variant_format_string_scan_type ("mm(@xy^a&*?@?)", NULL, NULL);
2777 g_assert (type == NULL);
2781 exit_on_abort (int signal)
2787 do_failed_test (const gchar *pattern)
2789 if (g_test_trap_fork (1000000, G_TEST_TRAP_SILENCE_STDERR))
2791 signal (SIGABRT, exit_on_abort);
2795 g_test_trap_assert_failed ();
2796 g_test_trap_assert_stderr (pattern);
2802 test_invalid_varargs (void)
2804 if (do_failed_test ("*GVariant format string*"))
2806 g_variant_new ("z");
2810 if (do_failed_test ("*valid GVariant format string as a prefix*"))
2814 g_variant_new_va ("z", &end, NULL);
2818 if (do_failed_test ("*type of `q' but * has a type of `y'*"))
2820 g_variant_get (g_variant_new ("y", 'a'), "q");
2826 check_and_free (GVariant *value,
2829 gchar *valstr = g_variant_print (value, FALSE);
2830 g_assert_cmpstr (str, ==, valstr);
2831 g_variant_unref (value);
2839 GVariantBuilder array;
2841 g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
2842 g_variant_builder_add (&array, "{sv}", "size",
2843 g_variant_new ("(ii)", 800, 600));
2844 g_variant_builder_add (&array, "{sv}", "title",
2845 g_variant_new_string ("Test case"));
2846 g_variant_builder_add_value (&array,
2847 g_variant_new_dict_entry (g_variant_new_string ("temperature"),
2848 g_variant_new_variant (
2849 g_variant_new_double (37.5))));
2850 check_and_free (g_variant_new ("(ma{sv}m(a{sv})ma{sv}ii)",
2851 NULL, FALSE, NULL, &array, 7777, 8888),
2852 "(nothing, nothing, {'size': <(800, 600)>, "
2853 "'title': <'Test case'>, "
2854 "'temperature': <37.5>}, "
2857 check_and_free (g_variant_new ("(imimimmimmimmi)",
2864 "(123, nothing, 123, nothing, just nothing, 123)");
2866 check_and_free (g_variant_new ("(ybnixd)",
2867 'a', 1, 22, 33, (guint64) 44, 5.5),
2868 "(0x61, true, 22, 33, 44, 5.5)");
2870 check_and_free (g_variant_new ("(@y?*rv)",
2871 g_variant_new ("y", 'a'),
2872 g_variant_new ("y", 'b'),
2873 g_variant_new ("y", 'c'),
2874 g_variant_new ("(y)", 'd'),
2875 g_variant_new ("y", 'e')),
2876 "(0x61, 0x62, 0x63, (0x64,), <byte 0x65>)");
2880 GVariantBuilder array;
2887 g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
2888 for (i = 0; i < 100; i++)
2890 number = g_strdup_printf ("%d", i);
2891 g_variant_builder_add (&array, "s", number);
2895 value = g_variant_builder_end (&array);
2896 g_variant_iter_init (&iter, value);
2899 while (g_variant_iter_loop (&iter, "s", &number))
2901 gchar *check = g_strdup_printf ("%d", i++);
2902 g_assert_cmpstr (number, ==, check);
2905 g_assert (number == NULL);
2906 g_assert (i == 100);
2908 g_variant_unref (value);
2910 g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
2911 for (i = 0; i < 100; i++)
2912 g_variant_builder_add (&array, "mi", i % 2 == 0, i);
2913 value = g_variant_builder_end (&array);
2916 g_variant_iter_init (&iter, value);
2917 while (g_variant_iter_loop (&iter, "mi", NULL, &val))
2918 g_assert (val == i++ || val == 0);
2919 g_assert (i == 100);
2922 g_variant_iter_init (&iter, value);
2923 while (g_variant_iter_loop (&iter, "mi", &just, &val))
2930 g_assert (val == this);
2935 g_assert (val == 0);
2938 g_assert (i == 100);
2940 g_variant_unref (value);
2944 const gchar *strvector[] = {"/hello", "/world", NULL};
2945 const gchar *test_strs[] = {"/foo", "/bar", "/baz" };
2946 GVariantBuilder builder;
2947 GVariantIter *array;
2955 g_variant_builder_init (&builder, G_VARIANT_TYPE ("ao"));
2956 g_variant_builder_add (&builder, "o", "/foo");
2957 g_variant_builder_add (&builder, "o", "/bar");
2958 g_variant_builder_add (&builder, "o", "/baz");
2959 value = g_variant_new("(ao^ao^a&o)", &builder, strvector, strvector);
2960 g_variant_iter_init (&tuple, value);
2961 g_variant_iter_next (&tuple, "ao", &array);
2964 while (g_variant_iter_loop (array, "o", &str))
2965 g_assert_cmpstr (str, ==, test_strs[i++]);
2968 g_variant_iter_free (array);
2971 g_variant_iter_init (&tuple, value);
2972 g_variant_iter_next (&tuple, "ao", &array);
2975 while (g_variant_iter_loop (array, "&o", &str))
2976 g_assert_cmpstr (str, ==, test_strs[i++]);
2979 g_variant_iter_free (array);
2981 g_variant_iter_next (&tuple, "^a&o", &strv);
2982 g_variant_iter_next (&tuple, "^ao", &my_strv);
2984 g_assert_cmpstr (strv[0], ==, "/hello");
2985 g_assert_cmpstr (strv[1], ==, "/world");
2986 g_assert (strv[2] == NULL);
2987 g_assert_cmpstr (my_strv[0], ==, "/hello");
2988 g_assert_cmpstr (my_strv[1], ==, "/world");
2989 g_assert (my_strv[2] == NULL);
2991 g_variant_unref (value);
2992 g_strfreev (my_strv);
2997 const gchar *strvector[] = { "i", "ii", "iii", "iv", "v", "vi", NULL };
2998 GVariantBuilder builder;
3007 g_variant_builder_init (&builder, G_VARIANT_TYPE ("aag"));
3008 g_variant_builder_open (&builder, G_VARIANT_TYPE ("ag"));
3009 for (i = 0; i < 6; i++)
3011 g_variant_builder_add (&builder, "g", strvector[i]);
3013 g_variant_builder_add (&builder, "&g", strvector[i]);
3014 g_variant_builder_close (&builder);
3015 g_variant_builder_add (&builder, "^ag", strvector);
3016 g_variant_builder_add (&builder, "^ag", strvector);
3017 value = g_variant_new ("aag", &builder);
3019 g_variant_iter_init (&iter, value);
3020 while (g_variant_iter_loop (&iter, "^ag", &strv))
3021 for (i = 0; i < 6; i++)
3022 g_assert_cmpstr (strv[i], ==, strvector[i]);
3024 g_variant_iter_init (&iter, value);
3025 while (g_variant_iter_loop (&iter, "^a&g", &strv))
3026 for (i = 0; i < 6; i++)
3027 g_assert_cmpstr (strv[i], ==, strvector[i]);
3029 g_variant_iter_init (&iter, value);
3030 while (g_variant_iter_loop (&iter, "ag", &i2))
3035 while (g_variant_iter_loop (i2, "g", &str))
3036 g_assert_cmpstr (str, ==, strvector[i++]);
3040 g_variant_iter_init (&iter, value);
3041 i3 = g_variant_iter_copy (&iter);
3042 while (g_variant_iter_loop (&iter, "@ag", &sub))
3044 gchar *str = g_variant_print (sub, TRUE);
3045 g_assert_cmpstr (str, ==,
3046 "[signature 'i', 'ii', 'iii', 'iv', 'v', 'vi']");
3050 if (do_failed_test ("*NULL has already been returned*"))
3052 g_variant_iter_next_value (&iter);
3057 while (g_variant_iter_loop (i3, "*", &sub))
3059 gchar *str = g_variant_print (sub, TRUE);
3060 g_assert_cmpstr (str, ==,
3061 "[signature 'i', 'ii', 'iii', 'iv', 'v', 'vi']");
3065 g_variant_iter_free (i3);
3067 for (i = 0; i < g_variant_n_children (value); i++)
3071 g_variant_get_child (value, i, "*", &sub);
3073 for (j = 0; j < g_variant_n_children (sub); j++)
3075 const gchar *str = NULL;
3078 g_variant_get_child (sub, j, "&g", &str);
3079 g_assert_cmpstr (str, ==, strvector[j]);
3081 cval = g_variant_get_child_value (sub, j);
3082 g_variant_get (cval, "&g", &str);
3083 g_assert_cmpstr (str, ==, strvector[j]);
3084 g_variant_unref (cval);
3087 g_variant_unref (sub);
3090 g_variant_unref (value);
3109 /* test all 'nothing' */
3110 value = g_variant_new ("(mymbmnmqmimumxmtmhmdmv)",
3113 FALSE, (gint16) 123,
3114 FALSE, (guint16) 123,
3115 FALSE, (gint32) 123,
3116 FALSE, (guint32) 123,
3117 FALSE, (gint64) 123,
3118 FALSE, (guint64) 123,
3120 FALSE, (gdouble) 37.5,
3124 g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3138 memset (justs, 1, sizeof justs);
3139 g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3151 g_assert (!(justs[0] || justs[1] || justs[2] || justs[3] || justs[4] ||
3152 justs[5] || justs[6] || justs[7] || justs[8] || justs[9]));
3155 memset (justs, 1, sizeof justs);
3156 byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3160 g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3161 &justs[0], &byteval,
3172 g_assert (!(justs[0] || justs[1] || justs[2] || justs[3] || justs[4] ||
3173 justs[5] || justs[6] || justs[7] || justs[8] || justs[9]));
3174 g_assert (byteval == '\0' && bval == FALSE);
3175 g_assert (i16val == 0 && u16val == 0 && i32val == 0 &&
3176 u32val == 0 && i64val == 0 && u64val == 0 &&
3177 hval == 0 && dval == 0.0);
3178 g_assert (vval == NULL);
3181 byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3185 g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3197 g_assert (byteval == '\0' && bval == FALSE);
3198 g_assert (i16val == 0 && u16val == 0 && i32val == 0 &&
3199 u32val == 0 && i64val == 0 && u64val == 0 &&
3200 hval == 0 && dval == 0.0);
3201 g_assert (vval == NULL);
3203 g_variant_unref (value);
3206 /* test all 'just' */
3207 value = g_variant_new ("(mymbmnmqmimumxmtmhmdmv)",
3211 TRUE, (guint16) 123,
3213 TRUE, (guint32) 123,
3215 TRUE, (guint64) 123,
3217 TRUE, (gdouble) 37.5,
3218 g_variant_new ("()"));
3221 g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3235 memset (justs, 0, sizeof justs);
3236 g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3248 g_assert (justs[0] && justs[1] && justs[2] && justs[3] && justs[4] &&
3249 justs[5] && justs[6] && justs[7] && justs[8] && justs[9]);
3252 memset (justs, 0, sizeof justs);
3253 byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3257 g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3258 &justs[0], &byteval,
3269 g_assert (justs[0] && justs[1] && justs[2] && justs[3] && justs[4] &&
3270 justs[5] && justs[6] && justs[7] && justs[8] && justs[9]);
3271 g_assert (byteval == 'a' && bval == TRUE);
3272 g_assert (i16val == 123 && u16val == 123 && i32val == 123 &&
3273 u32val == 123 && i64val == 123 && u64val == 123 &&
3274 hval == -1 && dval == 37.5);
3275 g_assert (g_variant_is_of_type (vval, G_VARIANT_TYPE_UNIT));
3276 g_variant_unref (vval);
3279 byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3283 g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3295 g_assert (byteval == 'a' && bval == TRUE);
3296 g_assert (i16val == 123 && u16val == 123 && i32val == 123 &&
3297 u32val == 123 && i64val == 123 && u64val == 123 &&
3298 hval == -1 && dval == 37.5);
3299 g_assert (g_variant_is_of_type (vval, G_VARIANT_TYPE_UNIT));
3300 g_variant_unref (vval);
3302 g_variant_unref (value);
3305 g_variant_type_info_assert_no_infos ();
3309 hash_get (GVariant *value,
3310 const gchar *format,
3313 const gchar *endptr = NULL;
3317 hash = g_str_has_suffix (format, "#");
3319 va_start (ap, format);
3320 g_variant_get_va (value, format, hash ? &endptr : NULL, &ap);
3324 g_assert (*endptr == '#');
3328 hash_new (const gchar *format,
3331 const gchar *endptr = NULL;
3336 hash = g_str_has_suffix (format, "#");
3338 va_start (ap, format);
3339 value = g_variant_new_va (format, hash ? &endptr : NULL, &ap);
3343 g_assert (*endptr == '#');
3355 value = hash_new ("i", 234);
3356 hash_get (value, "i", &x);
3357 g_assert (x == 234);
3358 g_variant_unref (value);
3361 value = hash_new ("i#", 234);
3362 hash_get (value, "i#", &x);
3363 g_assert (x == 234);
3364 g_variant_unref (value);
3366 g_variant_type_info_assert_no_infos ();
3370 test_builder_memory (void)
3372 GVariantBuilder *hb;
3375 hb = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
3376 g_variant_builder_open (hb, G_VARIANT_TYPE_ARRAY);
3377 g_variant_builder_open (hb, G_VARIANT_TYPE_ARRAY);
3378 g_variant_builder_open (hb, G_VARIANT_TYPE_ARRAY);
3379 g_variant_builder_add (hb, "s", "some value");
3380 g_variant_builder_ref (hb);
3381 g_variant_builder_unref (hb);
3382 g_variant_builder_unref (hb);
3384 hb = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
3385 g_variant_builder_unref (hb);
3387 hb = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
3388 g_variant_builder_clear (hb);
3389 g_variant_builder_unref (hb);
3391 g_variant_builder_init (&sb, G_VARIANT_TYPE_ARRAY);
3392 g_variant_builder_open (&sb, G_VARIANT_TYPE_ARRAY);
3393 g_variant_builder_open (&sb, G_VARIANT_TYPE_ARRAY);
3394 g_variant_builder_add (&sb, "s", "some value");
3395 g_variant_builder_clear (&sb);
3397 g_variant_type_info_assert_no_infos ();
3403 GVariant *items[4096];
3407 table = g_hash_table_new_full (g_variant_hash, g_variant_equal,
3408 (GDestroyNotify ) g_variant_unref,
3411 for (i = 0; i < G_N_ELEMENTS (items); i++)
3417 tree = tree_instance_new (NULL, 0);
3418 items[i] = tree_instance_get_gvariant (tree);
3419 tree_instance_free (tree);
3421 for (j = 0; j < i; j++)
3422 if (g_variant_equal (items[i], items[j]))
3424 g_variant_unref (items[i]);
3428 g_hash_table_insert (table,
3429 g_variant_ref_sink (items[i]),
3430 GINT_TO_POINTER (i));
3433 for (i = 0; i < G_N_ELEMENTS (items); i++)
3437 result = g_hash_table_lookup (table, items[i]);
3438 g_assert_cmpint (GPOINTER_TO_INT (result), ==, i);
3441 g_hash_table_unref (table);
3443 g_variant_type_info_assert_no_infos ();
3449 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
3450 # define native16(x) x, 0
3451 # define swapped16(x) 0, x
3453 # define native16(x) 0, x
3454 # define swapped16(x) x, 0
3456 /* all kinds of of crazy randomised testing already performed on the
3457 * byteswapper in the /gvariant/serialiser/byteswap test and all kinds
3458 * of crazy randomised testing performed against the serialiser
3459 * normalisation functions in the /gvariant/serialiser/fuzz/ tests.
3461 * just test a few simple cases here to make sure they each work
3463 guchar valid_data[] = { 'a', '\0', swapped16(66), 2,
3465 'b', '\0', swapped16(77), 2,
3467 guchar corrupt_data[] = { 'a', '\0', swapped16(66), 2,
3469 'b', '\0', swapped16(77), 2,
3471 GVariant *value, *swapped;
3472 gchar *string, *string2;
3476 value = g_variant_new_from_data (G_VARIANT_TYPE ("a(sn)"),
3477 valid_data, sizeof valid_data, TRUE,
3479 swapped = g_variant_byteswap (value);
3480 g_variant_unref (value);
3481 g_assert (g_variant_get_size (swapped) == 13);
3482 string = g_variant_print (swapped, FALSE);
3483 g_variant_unref (swapped);
3484 g_assert_cmpstr (string, ==, "[('a', 66), ('b', 77)]");
3487 /* untrusted but valid */
3488 value = g_variant_new_from_data (G_VARIANT_TYPE ("a(sn)"),
3489 valid_data, sizeof valid_data, FALSE,
3491 swapped = g_variant_byteswap (value);
3492 g_variant_unref (value);
3493 g_assert (g_variant_get_size (swapped) == 13);
3494 string = g_variant_print (swapped, FALSE);
3495 g_variant_unref (swapped);
3496 g_assert_cmpstr (string, ==, "[('a', 66), ('b', 77)]");
3499 /* untrusted, invalid */
3500 value = g_variant_new_from_data (G_VARIANT_TYPE ("a(sn)"),
3501 corrupt_data, sizeof corrupt_data, FALSE,
3503 string = g_variant_print (value, FALSE);
3504 swapped = g_variant_byteswap (value);
3505 g_variant_unref (value);
3506 g_assert (g_variant_get_size (swapped) == 13);
3507 value = g_variant_byteswap (swapped);
3508 g_variant_unref (swapped);
3509 string2 = g_variant_print (value, FALSE);
3510 g_assert (g_variant_get_size (value) == 13);
3511 g_variant_unref (value);
3512 g_assert_cmpstr (string, ==, string2);
3526 tree = tree_instance_new (NULL, 3);
3527 value = tree_instance_get_gvariant (tree);
3528 tree_instance_free (tree);
3530 pt = g_variant_print (value, TRUE);
3531 p = g_variant_print (value, FALSE);
3533 parsed = g_variant_parse (NULL, pt, NULL, NULL, NULL);
3534 res = g_variant_print (parsed, FALSE);
3535 g_assert_cmpstr (p, ==, res);
3536 g_variant_unref (parsed);
3539 parsed = g_variant_parse (g_variant_get_type (value), p,
3541 res = g_variant_print (parsed, TRUE);
3542 g_assert_cmpstr (pt, ==, res);
3543 g_variant_unref (parsed);
3546 g_variant_unref (value);
3556 for (i = 0; i < 100; i++)
3567 for (i = 0; i < 256; i++)
3570 val = g_variant_new_string (str);
3571 p = g_variant_print (val, FALSE);
3572 g_variant_unref (val);
3574 val = g_variant_parse (NULL, p, NULL, NULL, NULL);
3575 p2 = g_variant_print (val, FALSE);
3577 g_assert_cmpstr (str, ==, g_variant_get_string (val, NULL));
3578 g_assert_cmpstr (p, ==, p2);
3580 g_variant_unref (val);
3585 /* another mini test */
3590 value = g_variant_parse (G_VARIANT_TYPE_INT32, "1 2 3", NULL, &end, NULL);
3591 g_assert_cmpint (g_variant_get_int32 (value), ==, 1);
3592 /* make sure endptr returning works */
3593 g_assert_cmpstr (end, ==, " 2 3");
3594 g_variant_unref (value);
3597 g_variant_type_info_assert_no_infos ();
3601 test_parse_failures (void)
3603 const gchar *test[] = {
3604 "[1, 2,", "6:", "expected value",
3605 "", "0:", "expected value",
3606 "(1, 2,", "6:", "expected value",
3607 "<1", "2:", "expected `>'",
3608 "[]", "0-2:", "unable to infer",
3609 "(,", "1:", "expected value",
3610 "[4,'']", "1-2,3-5:", "common type",
3611 "[4, '', 5]", "1-2,4-6:", "common type",
3612 "['', 4, 5]", "1-3,5-6:", "common type",
3613 "[4, 5, '']", "1-2,7-9:", "common type",
3614 "[[4], [], ['']]", "1-4,10-14:", "common type",
3615 "[[], [4], ['']]", "5-8,10-14:", "common type",
3616 "just", "4:", "expected value",
3617 "nothing", "0-7:", "unable to infer",
3618 "just [4, '']", "6-7,9-11:", "common type",
3619 "[[4,'']]", "2-3,4-6:", "common type",
3620 "([4,''],)", "2-3,4-6:", "common type",
3622 "{}", "0-2:", "unable to infer",
3623 "{[1,2],[3,4]}", "0-13:", "basic types",
3624 "{[1,2]:[3,4]}", "0-13:", "basic types",
3625 "justt", "0-5:", "unknown keyword",
3626 "nothng", "0-6:", "unknown keyword",
3627 "uint33", "0-6:", "unknown keyword",
3628 "@mi just ''", "9-11:", "can not parse as",
3629 "@ai ['']", "5-7:", "can not parse as",
3630 "@(i) ('',)", "6-8:", "can not parse as",
3631 "[[], 5]", "1-3,5-6:", "common type",
3632 "[[5], 5]", "1-4,6-7:", "common type",
3633 "5 5", "2:", "expected end of input",
3634 "[5, [5, '']]", "5-6,8-10:", "common type",
3635 "@i just 5", "3-9:", "can not parse as",
3636 "@i nothing", "3-10:", "can not parse as",
3637 "@i []", "3-5:", "can not parse as",
3638 "@i ()", "3-5:", "can not parse as",
3639 "@ai (4,)", "4-8:", "can not parse as",
3640 "@(i) []", "5-7:", "can not parse as",
3641 "(5 5)", "3:", "expected `,'",
3642 "[5 5]", "3:", "expected `,' or `]'",
3643 "(5, 5 5)", "6:", "expected `,' or `)'",
3644 "[5, 5 5]", "6:", "expected `,' or `]'",
3645 "<@i []>", "4-6:", "can not parse as",
3646 "<[5 5]>", "4:", "expected `,' or `]'",
3647 "{[4,''],5}", "2-3,4-6:", "common type",
3648 "{5,[4,'']}", "4-5,6-8:", "common type",
3649 "@i {1,2}", "3-8:", "can not parse as",
3650 "{@i '', 5}", "4-6:", "can not parse as",
3651 "{5, @i ''}", "7-9:", "can not parse as",
3652 "@ai {}", "4-6:", "can not parse as",
3653 "{@i '': 5}", "4-6:", "can not parse as",
3654 "{5: @i ''}", "7-9:", "can not parse as",
3655 "{<4,5}", "3:", "expected `>'",
3656 "{4,<5}", "5:", "expected `>'",
3657 "{4,5,6}", "4:", "expected `}'",
3658 "{5 5}", "3:", "expected `:' or `,'",
3659 "{4: 5: 6}", "5:", "expected `,' or `}'",
3660 "{4:5,<6:7}", "7:", "expected `>'",
3661 "{4:5,6:<7}", "9:", "expected `>'",
3662 "{4:5,6 7}", "7:", "expected `:'",
3663 "@o 'foo'", "3-8:", "object path",
3664 "@g 'zzz'", "3-8:", "signature",
3665 "@i true", "3-7:", "can not parse as",
3666 "@z 4", "0-2:", "invalid type",
3667 "@a* []", "0-3:", "definite",
3668 "@ai [3 3]", "7:", "expected `,' or `]'",
3669 "18446744073709551616", "0-20:", "too big for any type",
3670 "-18446744073709551616", "0-21:", "too big for any type",
3671 "byte 256", "5-8:", "out of range for type",
3672 "byte -1", "5-7:", "out of range for type",
3673 "int16 32768", "6-11:", "out of range for type",
3674 "int16 -32769", "6-12:", "out of range for type",
3675 "uint16 -1", "7-9:", "out of range for type",
3676 "uint16 65536", "7-12:", "out of range for type",
3677 "2147483648", "0-10:", "out of range for type",
3678 "-2147483649", "0-11:", "out of range for type",
3679 "uint32 -1", "7-9:", "out of range for type",
3680 "uint32 4294967296", "7-17:", "out of range for type",
3681 "@x 9223372036854775808", "3-22:", "out of range for type",
3682 "@x -9223372036854775809", "3-23:", "out of range for type",
3683 "@t -1", "3-5:", "out of range for type",
3684 "@t 18446744073709551616", "3-23:", "too big for any type",
3685 "handle 2147483648", "7-17:", "out of range for type",
3686 "handle -2147483649", "7-18:", "out of range for type",
3687 "1.798e308", "0-9:", "too big for any type",
3688 "37.5a488", "4-5:", "invalid character",
3689 "0x7ffgf", "5-6:", "invalid character",
3690 "07758", "4-5:", "invalid character",
3691 "123a5", "3-4:", "invalid character",
3692 "@ai 123", "4-7:", "can not parse as",
3693 "'\"\\'", "0-4:", "unterminated string",
3694 "'\"\\'\\", "0-5:", "unterminated string",
3695 "boolean 4", "8-9:", "can not parse as",
3696 "int32 true", "6-10:", "can not parse as",
3697 "[double 5, int32 5]", "1-9,11-18:", "common type",
3698 "string 4", "7-8:", "can not parse as"
3702 for (i = 0; i < G_N_ELEMENTS (test); i += 3)
3704 GError *error = NULL;
3707 value = g_variant_parse (NULL, test[i], NULL, NULL, &error);
3708 g_assert (value == NULL);
3710 if (!strstr (error->message, test[i+2]))
3711 g_error ("test %d: Can't find `%s' in `%s'", i / 3,
3712 test[i+2], error->message);
3714 if (!g_str_has_prefix (error->message, test[i+1]))
3715 g_error ("test %d: Expected location `%s' in `%s'", i / 3,
3716 test[i+1], error->message);
3718 g_error_free (error);
3723 test_parse_positional (void)
3726 check_and_free (g_variant_new_parsed ("[('one', 1), (%s, 2),"
3727 " ('three', %i)]", "two", 3),
3728 "[('one', 1), ('two', 2), ('three', 3)]");
3729 value = g_variant_new_parsed ("[('one', 1), (%s, 2),"
3730 " ('three', %u)]", "two", 3);
3731 g_assert (g_variant_is_of_type (value, G_VARIANT_TYPE ("a(su)")));
3732 check_and_free (value, "[('one', 1), ('two', 2), ('three', 3)]");
3733 check_and_free (g_variant_new_parsed ("{%s:%i}", "one", 1), "{'one': 1}");
3735 if (do_failed_test ("*GVariant format string*"))
3737 g_variant_new_parsed ("%z");
3741 if (do_failed_test ("*can not parse as*"))
3743 g_variant_new_parsed ("uint32 %i", 2);
3747 if (do_failed_test ("*expected GVariant of type `i'*"))
3749 g_variant_new_parsed ("%@i", g_variant_new_uint32 (2));
3755 main (int argc, char **argv)
3759 g_test_init (&argc, &argv, NULL);
3761 g_test_add_func ("/gvariant/type", test_gvarianttype);
3762 g_test_add_func ("/gvariant/typeinfo", test_gvarianttypeinfo);
3763 g_test_add_func ("/gvariant/serialiser/maybe", test_maybes);
3764 g_test_add_func ("/gvariant/serialiser/array", test_arrays);
3765 g_test_add_func ("/gvariant/serialiser/tuple", test_tuples);
3766 g_test_add_func ("/gvariant/serialiser/variant", test_variants);
3767 g_test_add_func ("/gvariant/serialiser/strings", test_strings);
3768 g_test_add_func ("/gvariant/serialiser/byteswap", test_byteswaps);
3770 for (i = 1; i <= 20; i += 4)
3774 testname = g_strdup_printf ("/gvariant/serialiser/fuzz/%d%%", i);
3775 g_test_add_data_func (testname, GINT_TO_POINTER (i),
3776 (gpointer) test_fuzzes);
3780 g_test_add_func ("/gvariant/utf8", test_utf8);
3781 g_test_add_func ("/gvariant/containers", test_containers);
3782 g_test_add_func ("/gvariant/format-strings", test_format_strings);
3783 g_test_add_func ("/gvariant/invalid-varargs", test_invalid_varargs);
3784 g_test_add_func ("/gvariant/varargs", test_varargs);
3785 g_test_add_func ("/gvariant/valist", test_valist);
3786 g_test_add_func ("/gvariant/builder-memory", test_builder_memory);
3787 g_test_add_func ("/gvariant/hashing", test_hashing);
3788 g_test_add_func ("/gvariant/byteswap", test_gv_byteswap);
3789 g_test_add_func ("/gvariant/parser", test_parses);
3790 g_test_add_func ("/gvariant/parse-failures", test_parse_failures);
3791 g_test_add_func ("/gvariant/parse-positional", test_parse_positional);
3793 return g_test_run ();