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 & 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 & 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 & 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,
1274 g_free (((gchar *) data) - flavour);
1278 align_malloc (gsize size)
1282 #ifdef HAVE_POSIX_MEMALIGN
1283 if (posix_memalign (&mem, 8, size))
1284 g_error ("posix_memalign failed");
1286 /* NOTE: there may be platforms that lack posix_memalign() and also
1287 * have malloc() that returns non-8-aligned. if so, we need to try
1290 mem = malloc (size);
1297 align_free (gpointer mem)
1303 append_offset (guchar **offset_ptr,
1309 guchar bytes[sizeof (gsize)];
1313 tmpvalue.integer = GSIZE_TO_LE (offset);
1314 memcpy (*offset_ptr, tmpvalue.bytes, offset_size);
1315 *offset_ptr += offset_size;
1319 prepend_offset (guchar **offset_ptr,
1325 guchar bytes[sizeof (gsize)];
1329 *offset_ptr -= offset_size;
1330 tmpvalue.integer = GSIZE_TO_LE (offset);
1331 memcpy (*offset_ptr, tmpvalue.bytes, offset_size);
1337 GVariantTypeInfo *type_info;
1338 RandomInstance *instance;
1342 instance = random_instance (NULL);
1345 const gchar *element;
1348 element = g_variant_type_info_get_type_string (instance->type_info);
1349 tmp = g_strdup_printf ("m%s", element);
1350 type_info = g_variant_type_info_get (G_VARIANT_TYPE (tmp));
1354 needed_size = g_variant_serialiser_needed_size (type_info,
1355 random_instance_filler,
1357 g_assert_cmpint (needed_size, ==, 0);
1359 needed_size = g_variant_serialiser_needed_size (type_info,
1360 random_instance_filler,
1361 (gpointer *) &instance, 1);
1363 if (instance->is_fixed_sized)
1364 g_assert_cmpint (needed_size, ==, instance->size);
1366 g_assert_cmpint (needed_size, ==, instance->size + 1);
1371 ptr = data = align_malloc (needed_size);
1372 append_instance_data (instance, &ptr);
1374 if (!instance->is_fixed_sized)
1377 g_assert_cmpint (ptr - data, ==, needed_size);
1384 alignment = (instance->alignment & ALIGN_BITS) + 1;
1386 for (flavour = 0; flavour < 8; flavour += alignment)
1388 GVariantSerialised serialised;
1389 GVariantSerialised child;
1391 serialised.type_info = type_info;
1392 serialised.data = flavoured_malloc (needed_size, flavour);
1393 serialised.size = needed_size;
1395 g_variant_serialiser_serialise (serialised,
1396 random_instance_filler,
1397 (gpointer *) &instance, 1);
1398 child = g_variant_serialised_get_child (serialised, 0);
1399 g_assert (child.type_info == instance->type_info);
1400 random_instance_assert (instance, child.data, child.size);
1401 g_variant_type_info_unref (child.type_info);
1402 flavoured_free (serialised.data, flavour);
1406 g_variant_type_info_unref (type_info);
1407 random_instance_free (instance);
1416 for (i = 0; i < 1000; i++)
1419 g_variant_type_info_assert_no_infos ();
1425 GVariantTypeInfo *element_info;
1426 GVariantTypeInfo *array_info;
1427 RandomInstance **instances;
1434 gchar *element_type, *array_type;
1436 element_type = random_type_string ();
1437 array_type = g_strdup_printf ("a%s", element_type);
1439 element_info = g_variant_type_info_get (G_VARIANT_TYPE (element_type));
1440 array_info = g_variant_type_info_get (G_VARIANT_TYPE (array_type));
1441 g_assert (g_variant_type_info_element (array_info) == element_info);
1443 g_free (element_type);
1444 g_free (array_type);
1450 n_children = g_test_rand_int_range (0, MAX_ARRAY_CHILDREN);
1451 instances = g_new (RandomInstance *, n_children);
1452 for (i = 0; i < n_children; i++)
1453 instances[i] = random_instance (element_info);
1456 needed_size = g_variant_serialiser_needed_size (array_info,
1457 random_instance_filler,
1458 (gpointer *) instances,
1462 gsize element_fixed_size;
1463 gsize body_size = 0;
1466 for (i = 0; i < n_children; i++)
1467 append_instance_size (instances[i], &body_size);
1469 g_variant_type_info_query (element_info, NULL, &element_fixed_size);
1471 if (!element_fixed_size)
1473 offset_size = calculate_offset_size (body_size, n_children);
1475 if (offset_size == 0)
1481 g_assert_cmpint (needed_size, ==, body_size + n_children * offset_size);
1485 guchar *offset_ptr, *body_ptr;
1488 body_ptr = data = align_malloc (needed_size);
1489 offset_ptr = body_ptr + needed_size - offset_size * n_children;
1491 for (i = 0; i < n_children; i++)
1493 append_instance_data (instances[i], &body_ptr);
1494 append_offset (&offset_ptr, body_ptr - data, offset_size);
1497 g_assert (body_ptr == data + needed_size - offset_size * n_children);
1498 g_assert (offset_ptr == data + needed_size);
1506 g_variant_type_info_query (array_info, &alignment, NULL);
1507 alignment = (alignment & ALIGN_BITS) + 1;
1509 for (flavour = 0; flavour < 8; flavour += alignment)
1511 GVariantSerialised serialised;
1513 serialised.type_info = array_info;
1514 serialised.data = flavoured_malloc (needed_size, flavour);
1515 serialised.size = needed_size;
1517 g_variant_serialiser_serialise (serialised, random_instance_filler,
1518 (gpointer *) instances, n_children);
1520 g_assert (memcmp (serialised.data, data, serialised.size) == 0);
1521 g_assert (g_variant_serialised_n_children (serialised) == n_children);
1523 for (i = 0; i < n_children; i++)
1525 GVariantSerialised child;
1527 child = g_variant_serialised_get_child (serialised, i);
1528 g_assert (child.type_info == instances[i]->type_info);
1529 random_instance_assert (instances[i], child.data, child.size);
1530 g_variant_type_info_unref (child.type_info);
1533 flavoured_free (serialised.data, flavour);
1540 for (i = 0; i < n_children; i++)
1541 random_instance_free (instances[i]);
1545 g_variant_type_info_unref (element_info);
1546 g_variant_type_info_unref (array_info);
1555 for (i = 0; i < 100; i++)
1558 g_variant_type_info_assert_no_infos ();
1564 GVariantTypeInfo *type_info;
1565 RandomInstance **instances;
1566 gboolean fixed_size;
1573 n_children = g_test_rand_int_range (0, MAX_TUPLE_CHILDREN);
1574 instances = g_new (RandomInstance *, n_children);
1577 GString *type_string;
1583 type_string = g_string_new ("(");
1584 for (i = 0; i < n_children; i++)
1588 instances[i] = random_instance (NULL);
1590 alignment |= instances[i]->alignment;
1591 if (!instances[i]->is_fixed_sized)
1594 str = g_variant_type_info_get_type_string (instances[i]->type_info);
1595 g_string_append (type_string, str);
1597 g_string_append_c (type_string, ')');
1599 type_info = g_variant_type_info_get (G_VARIANT_TYPE (type_string->str));
1600 g_string_free (type_string, TRUE);
1603 needed_size = g_variant_serialiser_needed_size (type_info,
1604 random_instance_filler,
1605 (gpointer *) instances,
1608 gsize body_size = 0;
1612 for (i = 0; i < n_children; i++)
1614 append_instance_size (instances[i], &body_size);
1616 if (i != n_children - 1 && !instances[i]->is_fixed_sized)
1622 body_size += (-body_size) & alignment;
1624 g_assert ((body_size == 0) == (n_children == 0));
1625 if (n_children == 0)
1629 offset_size = calculate_offset_size (body_size, offsets);
1630 g_assert_cmpint (needed_size, ==, body_size + offsets * offset_size);
1638 body_ptr = data = align_malloc (needed_size);
1639 ofs_ptr = body_ptr + needed_size;
1641 for (i = 0; i < n_children; i++)
1643 append_instance_data (instances[i], &body_ptr);
1645 if (i != n_children - 1 && !instances[i]->is_fixed_sized)
1646 prepend_offset (&ofs_ptr, body_ptr - data, offset_size);
1651 while (((gsize) body_ptr) & alignment)
1654 g_assert ((body_ptr == data) == (n_children == 0));
1655 if (n_children == 0)
1661 g_assert (body_ptr == ofs_ptr);
1668 alignment = (alignment & ALIGN_BITS) + 1;
1670 for (flavour = 0; flavour < 8; flavour += alignment)
1672 GVariantSerialised serialised;
1674 serialised.type_info = type_info;
1675 serialised.data = flavoured_malloc (needed_size, flavour);
1676 serialised.size = needed_size;
1678 g_variant_serialiser_serialise (serialised, random_instance_filler,
1679 (gpointer *) instances, n_children);
1681 g_assert (memcmp (serialised.data, data, serialised.size) == 0);
1682 g_assert (g_variant_serialised_n_children (serialised) == n_children);
1684 for (i = 0; i < n_children; i++)
1686 GVariantSerialised child;
1688 child = g_variant_serialised_get_child (serialised, i);
1689 g_assert (child.type_info == instances[i]->type_info);
1690 random_instance_assert (instances[i], child.data, child.size);
1691 g_variant_type_info_unref (child.type_info);
1694 flavoured_free (serialised.data, flavour);
1701 for (i = 0; i < n_children; i++)
1702 random_instance_free (instances[i]);
1706 g_variant_type_info_unref (type_info);
1715 for (i = 0; i < 100; i++)
1718 g_variant_type_info_assert_no_infos ();
1724 GVariantTypeInfo *type_info;
1725 RandomInstance *instance;
1726 const gchar *type_string;
1731 type_info = g_variant_type_info_get (G_VARIANT_TYPE_VARIANT);
1732 instance = random_instance (NULL);
1734 type_string = g_variant_type_info_get_type_string (instance->type_info);
1735 len = strlen (type_string);
1737 needed_size = g_variant_serialiser_needed_size (type_info,
1738 random_instance_filler,
1739 (gpointer *) &instance, 1);
1741 g_assert_cmpint (needed_size, ==, instance->size + 1 + len);
1746 ptr = data = align_malloc (needed_size);
1747 append_instance_data (instance, &ptr);
1749 memcpy (ptr, type_string, len);
1752 g_assert (data + needed_size == ptr);
1759 /* variants are always 8-aligned */
1760 alignment = ALIGN_BITS + 1;
1762 for (flavour = 0; flavour < 8; flavour += alignment)
1764 GVariantSerialised serialised;
1765 GVariantSerialised child;
1767 serialised.type_info = type_info;
1768 serialised.data = flavoured_malloc (needed_size, flavour);
1769 serialised.size = needed_size;
1771 g_variant_serialiser_serialise (serialised, random_instance_filler,
1772 (gpointer *) &instance, 1);
1774 g_assert (memcmp (serialised.data, data, serialised.size) == 0);
1775 g_assert (g_variant_serialised_n_children (serialised) == 1);
1777 child = g_variant_serialised_get_child (serialised, 0);
1778 g_assert (child.type_info == instance->type_info);
1779 random_instance_check (instance, child.data, child.size);
1781 g_variant_type_info_unref (child.type_info);
1782 flavoured_free (serialised.data, flavour);
1786 g_variant_type_info_unref (type_info);
1787 random_instance_free (instance);
1792 test_variants (void)
1796 for (i = 0; i < 100; i++)
1799 g_variant_type_info_assert_no_infos ();
1812 #define is_objpath is_string | 2
1813 #define is_sig is_string | 4
1815 { is_nval, 0, NULL },
1816 { is_nval, 13, "hello\xffworld!" },
1817 { is_string, 13, "hello world!" },
1818 { is_nval, 13, "hello world\0" },
1819 { is_nval, 13, "hello\0world!" },
1820 { is_nval, 12, "hello world!" },
1822 { is_objpath, 2, "/" },
1823 { is_objpath, 3, "/a" },
1824 { is_string, 3, "//" },
1825 { is_objpath, 11, "/some/path" },
1826 { is_string, 12, "/some/path/" },
1827 { is_nval, 11, "/some\0path" },
1828 { is_string, 11, "/some\\path" },
1829 { is_string, 12, "/some//path" },
1830 { is_string, 12, "/some-/path" },
1834 { is_sig, 5, "(si)" },
1835 { is_string, 4, "(si" },
1836 { is_string, 2, "*" },
1837 { is_sig, 3, "ai" },
1838 { is_string, 3, "mi" },
1839 { is_string, 2, "r" },
1840 { is_sig, 15, "(yyy{sv}ssiai)" },
1841 { is_string, 16, "(yyy{yv}ssiai))" },
1842 { is_string, 15, "(yyy{vv}ssiai)" },
1843 { is_string, 15, "(yyy{sv)ssiai}" }
1847 for (i = 0; i < G_N_ELEMENTS (test_cases); i++)
1851 flags = g_variant_serialiser_is_string (test_cases[i].data,
1855 flags |= g_variant_serialiser_is_object_path (test_cases[i].data,
1859 flags |= g_variant_serialiser_is_signature (test_cases[i].data,
1863 g_assert (flags == test_cases[i].flags);
1867 typedef struct _TreeInstance TreeInstance;
1868 struct _TreeInstance
1870 GVariantTypeInfo *info;
1872 TreeInstance **children;
1883 static GVariantType *
1884 make_random_definite_type (int depth)
1886 GString *description;
1887 GString *type_string;
1890 description = g_string_new (NULL);
1891 type_string = g_string_new (NULL);
1892 type = append_type_string (type_string, description, TRUE, depth);
1893 g_string_free (description, TRUE);
1894 g_string_free (type_string, TRUE);
1900 make_random_string (gchar *string,
1902 const GVariantType *type)
1906 /* create strings that are valid signature strings */
1907 #define good_chars "bynqiuxthdsog"
1909 for (i = 0; i < size - 1; i++)
1910 string[i] = good_chars[g_test_rand_int_range (0, strlen (good_chars))];
1913 /* in case we need an object path, prefix a '/' */
1914 if (*g_variant_type_peek_string (type) == 'o')
1920 static TreeInstance *
1921 tree_instance_new (const GVariantType *type,
1924 const GVariantType *child_type = NULL;
1925 GVariantType *mytype = NULL;
1926 TreeInstance *instance;
1927 gboolean is_tuple_type;
1930 type = mytype = make_random_definite_type (depth);
1932 instance = g_slice_new (TreeInstance);
1933 instance->info = g_variant_type_info_get (type);
1934 instance->children = NULL;
1935 instance->n_children = 0;
1936 instance->data_size = 0;
1938 is_tuple_type = FALSE;
1940 switch (*g_variant_type_peek_string (type))
1942 case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
1943 instance->n_children = g_test_rand_int_range (0, 2);
1944 child_type = g_variant_type_element (type);
1947 case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
1948 instance->n_children = g_test_rand_int_range (0, MAX_ARRAY_CHILDREN);
1949 child_type = g_variant_type_element (type);
1952 case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
1953 case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
1954 instance->n_children = g_variant_type_n_items (type);
1955 child_type = g_variant_type_first (type);
1956 is_tuple_type = TRUE;
1959 case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
1960 instance->n_children = 1;
1965 instance->data.integer = g_test_rand_int_range (0, 2);
1966 instance->data_size = 1;
1970 instance->data.integer = g_test_rand_int ();
1971 instance->data_size = 1;
1975 instance->data.integer = g_test_rand_int ();
1976 instance->data_size = 2;
1979 case 'i': case 'u': case 'h':
1980 instance->data.integer = g_test_rand_int ();
1981 instance->data_size = 4;
1985 instance->data.integer = g_test_rand_int ();
1986 instance->data.integer <<= 32;
1987 instance->data.integer |= (guint32) g_test_rand_int ();
1988 instance->data_size = 8;
1992 instance->data.floating = g_test_rand_double ();
1993 instance->data_size = 8;
1996 case 's': case 'o': case 'g':
1997 instance->data_size = g_test_rand_int_range (10, 20);
1998 make_random_string (instance->data.string, instance->data_size, type);
2002 if (instance->data_size == 0)
2003 /* no data -> it is a container */
2007 instance->children = g_new (TreeInstance *, instance->n_children);
2009 for (i = 0; i < instance->n_children; i++)
2011 instance->children[i] = tree_instance_new (child_type, depth - 1);
2014 child_type = g_variant_type_next (child_type);
2017 g_assert (!is_tuple_type || child_type == NULL);
2020 g_variant_type_free (mytype);
2026 tree_instance_free (TreeInstance *instance)
2030 g_variant_type_info_unref (instance->info);
2031 for (i = 0; i < instance->n_children; i++)
2032 tree_instance_free (instance->children[i]);
2033 g_free (instance->children);
2034 g_slice_free (TreeInstance, instance);
2037 static gboolean i_am_writing_byteswapped;
2040 tree_filler (GVariantSerialised *serialised,
2043 TreeInstance *instance = data;
2045 if (serialised->type_info == NULL)
2046 serialised->type_info = instance->info;
2048 if (instance->data_size == 0)
2049 /* is a container */
2051 if (serialised->size == 0)
2053 g_variant_serialiser_needed_size (instance->info, tree_filler,
2054 (gpointer *) instance->children,
2055 instance->n_children);
2057 if (serialised->data)
2058 g_variant_serialiser_serialise (*serialised, tree_filler,
2059 (gpointer *) instance->children,
2060 instance->n_children);
2065 if (serialised->size == 0)
2066 serialised->size = instance->data_size;
2068 if (serialised->data)
2070 switch (instance->data_size)
2073 *serialised->data = instance->data.integer;
2078 guint16 value = instance->data.integer;
2080 if (i_am_writing_byteswapped)
2081 value = GUINT16_SWAP_LE_BE (value);
2083 *(guint16 *) serialised->data = value;
2089 guint32 value = instance->data.integer;
2091 if (i_am_writing_byteswapped)
2092 value = GUINT32_SWAP_LE_BE (value);
2094 *(guint32 *) serialised->data = value;
2100 guint64 value = instance->data.integer;
2102 if (i_am_writing_byteswapped)
2103 value = GUINT64_SWAP_LE_BE (value);
2105 *(guint64 *) serialised->data = value;
2110 memcpy (serialised->data,
2111 instance->data.string,
2112 instance->data_size);
2120 check_tree (TreeInstance *instance,
2121 GVariantSerialised serialised)
2123 if (instance->info != serialised.type_info)
2126 if (instance->data_size == 0)
2127 /* is a container */
2131 if (g_variant_serialised_n_children (serialised) !=
2132 instance->n_children)
2135 for (i = 0; i < instance->n_children; i++)
2137 GVariantSerialised child;
2138 gpointer data = NULL;
2141 child = g_variant_serialised_get_child (serialised, i);
2142 if (child.size && child.data == NULL)
2143 child.data = data = g_malloc0 (child.size);
2144 ok = check_tree (instance->children[i], child);
2145 g_variant_type_info_unref (child.type_info);
2157 switch (instance->data_size)
2160 g_assert (serialised.size == 1);
2161 return *(guint8 *) serialised.data ==
2162 (guint8) instance->data.integer;
2165 g_assert (serialised.size == 2);
2166 return *(guint16 *) serialised.data ==
2167 (guint16) instance->data.integer;
2170 g_assert (serialised.size == 4);
2171 return *(guint32 *) serialised.data ==
2172 (guint32) instance->data.integer;
2175 g_assert (serialised.size == 8);
2176 return *(guint64 *) serialised.data ==
2177 (guint64) instance->data.integer;
2180 if (serialised.size != instance->data_size)
2183 return memcmp (serialised.data,
2184 instance->data.string,
2185 instance->data_size) == 0;
2191 serialise_tree (TreeInstance *tree,
2192 GVariantSerialised *serialised)
2194 GVariantSerialised empty = { };
2196 *serialised = empty;
2197 tree_filler (serialised, tree);
2198 serialised->data = g_malloc (serialised->size);
2199 tree_filler (serialised, tree);
2203 test_byteswap (void)
2205 GVariantSerialised one, two;
2208 tree = tree_instance_new (NULL, 3);
2209 serialise_tree (tree, &one);
2211 i_am_writing_byteswapped = TRUE;
2212 serialise_tree (tree, &two);
2213 i_am_writing_byteswapped = FALSE;
2215 g_variant_serialised_byteswap (two);
2217 g_assert_cmpint (one.size, ==, two.size);
2218 g_assert (memcmp (one.data, two.data, one.size) == 0);
2220 tree_instance_free (tree);
2226 test_byteswaps (void)
2230 for (i = 0; i < 200; i++)
2233 g_variant_type_info_assert_no_infos ();
2237 test_fuzz (gdouble *fuzziness)
2239 GVariantSerialised serialised;
2242 /* make an instance */
2243 tree = tree_instance_new (NULL, 3);
2246 serialise_tree (tree, &serialised);
2248 g_assert (g_variant_serialised_is_normal (serialised));
2249 g_assert (check_tree (tree, serialised));
2251 if (serialised.size)
2253 gboolean fuzzed = FALSE;
2260 for (i = 0; i < serialised.size; i++)
2261 if (randomly (*fuzziness))
2263 serialised.data[i] += g_test_rand_int_range (1, 256);
2268 /* at least one byte in the serialised data has changed.
2270 * this means that at least one of the following is true:
2272 * - the serialised data now represents a different value:
2273 * check_tree() will return FALSE
2275 * - the serialised data is in non-normal form:
2276 * g_variant_serialiser_is_normal() will return FALSE
2278 * we always do both checks to increase exposure of the serialiser
2281 a = g_variant_serialised_is_normal (serialised);
2282 b = check_tree (tree, serialised);
2284 g_assert (!a || !b);
2287 tree_instance_free (tree);
2288 g_free (serialised.data);
2293 test_fuzzes (gpointer data)
2298 fuzziness = GPOINTER_TO_INT (data) / 100.;
2300 for (i = 0; i < 200; i++)
2301 test_fuzz (&fuzziness);
2303 g_variant_type_info_assert_no_infos ();
2307 tree_instance_get_gvariant (TreeInstance *tree)
2309 const GVariantType *type;
2312 type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
2314 switch (g_variant_type_info_get_type_char (tree->info))
2316 case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
2318 const GVariantType *child_type;
2321 if (tree->n_children)
2322 child = tree_instance_get_gvariant (tree->children[0]);
2326 child_type = g_variant_type_element (type);
2328 if (child != NULL && randomly (0.5))
2331 result = g_variant_new_maybe (child_type, child);
2335 case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
2337 const GVariantType *child_type;
2338 GVariant **children;
2341 children = g_new (GVariant *, tree->n_children);
2342 for (i = 0; i < tree->n_children; i++)
2343 children[i] = tree_instance_get_gvariant (tree->children[i]);
2345 child_type = g_variant_type_element (type);
2347 if (i > 0 && randomly (0.5))
2350 result = g_variant_new_array (child_type, children, tree->n_children);
2355 case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
2357 GVariant **children;
2360 children = g_new (GVariant *, tree->n_children);
2361 for (i = 0; i < tree->n_children; i++)
2362 children[i] = tree_instance_get_gvariant (tree->children[i]);
2364 result = g_variant_new_tuple (children, tree->n_children);
2369 case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
2371 GVariant *key, *val;
2373 g_assert (tree->n_children == 2);
2375 key = tree_instance_get_gvariant (tree->children[0]);
2376 val = tree_instance_get_gvariant (tree->children[1]);
2378 result = g_variant_new_dict_entry (key, val);
2382 case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
2386 g_assert (tree->n_children == 1);
2388 value = tree_instance_get_gvariant (tree->children[0]);
2389 result = g_variant_new_variant (value);
2394 result = g_variant_new_boolean (tree->data.integer > 0);
2398 result = g_variant_new_byte (tree->data.integer);
2402 result = g_variant_new_int16 (tree->data.integer);
2406 result = g_variant_new_uint16 (tree->data.integer);
2410 result = g_variant_new_int32 (tree->data.integer);
2414 result = g_variant_new_uint32 (tree->data.integer);
2418 result = g_variant_new_int64 (tree->data.integer);
2422 result = g_variant_new_uint64 (tree->data.integer);
2426 result = g_variant_new_handle (tree->data.integer);
2430 result = g_variant_new_double (tree->data.floating);
2434 result = g_variant_new_string (tree->data.string);
2438 result = g_variant_new_object_path (tree->data.string);
2442 result = g_variant_new_signature (tree->data.string);
2446 g_assert_not_reached ();
2453 tree_instance_check_gvariant (TreeInstance *tree,
2456 const GVariantType *type;
2458 type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
2459 g_assert (g_variant_is_of_type (value, type));
2461 switch (g_variant_type_info_get_type_char (tree->info))
2463 case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
2468 child = g_variant_get_maybe (value);
2470 if (child != NULL && tree->n_children == 1)
2471 equal = tree_instance_check_gvariant (tree->children[0], child);
2472 else if (child == NULL && tree->n_children == 0)
2478 g_variant_unref (child);
2484 case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
2485 case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
2486 case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
2490 if (g_variant_n_children (value) != tree->n_children)
2493 for (i = 0; i < tree->n_children; i++)
2498 child = g_variant_get_child_value (value, i);
2499 equal = tree_instance_check_gvariant (tree->children[i], child);
2500 g_variant_unref (child);
2510 case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
2512 const gchar *str1, *str2;
2516 child = g_variant_get_variant (value);
2517 str1 = g_variant_get_type_string (child);
2518 str2 = g_variant_type_info_get_type_string (tree->children[0]->info);
2519 /* GVariant only keeps one copy of type strings around */
2520 equal = str1 == str2 &&
2521 tree_instance_check_gvariant (tree->children[0], child);
2523 g_variant_unref (child);
2530 return g_variant_get_boolean (value) == tree->data.integer;
2533 return g_variant_get_byte (value) == (guchar) tree->data.integer;
2536 return g_variant_get_int16 (value) == (gint16) tree->data.integer;
2539 return g_variant_get_uint16 (value) == (guint16) tree->data.integer;
2542 return g_variant_get_int32 (value) == (gint32) tree->data.integer;
2545 return g_variant_get_uint32 (value) == (guint32) tree->data.integer;
2548 return g_variant_get_int64 (value) == (gint64) tree->data.integer;
2551 return g_variant_get_uint64 (value) == (guint64) tree->data.integer;
2554 return g_variant_get_handle (value) == (gint32) tree->data.integer;
2558 gdouble floating = g_variant_get_double (value);
2560 return memcmp (&floating, &tree->data.floating, sizeof floating) == 0;
2566 return strcmp (g_variant_get_string (value, NULL),
2567 tree->data.string) == 0;
2570 g_assert_not_reached ();
2575 tree_instance_build_gvariant (TreeInstance *tree,
2576 GVariantBuilder *builder,
2579 const GVariantType *type;
2581 type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
2583 if (g_variant_type_is_container (type))
2587 /* force GVariantBuilder to guess the type half the time */
2588 if (guess_ok && randomly (0.5))
2590 if (g_variant_type_is_array (type) && tree->n_children)
2591 type = G_VARIANT_TYPE_ARRAY;
2593 if (g_variant_type_is_maybe (type) && tree->n_children)
2594 type = G_VARIANT_TYPE_MAYBE;
2596 if (g_variant_type_is_tuple (type))
2597 type = G_VARIANT_TYPE_TUPLE;
2599 if (g_variant_type_is_dict_entry (type))
2600 type = G_VARIANT_TYPE_DICT_ENTRY;
2605 g_variant_builder_open (builder, type);
2607 for (i = 0; i < tree->n_children; i++)
2608 tree_instance_build_gvariant (tree->children[i], builder, guess_ok);
2610 g_variant_builder_close (builder);
2613 g_variant_builder_add_value (builder, tree_instance_get_gvariant (tree));
2618 tree_instance_check_iter (TreeInstance *tree,
2623 value = g_variant_iter_next_value (iter);
2625 if (g_variant_is_container (value))
2629 iter = g_variant_iter_new (value);
2630 g_variant_unref (value);
2632 if (g_variant_iter_n_children (iter) != tree->n_children)
2634 g_variant_iter_free (iter);
2638 for (i = 0; i < tree->n_children; i++)
2639 if (!tree_instance_check_iter (tree->children[i], iter))
2641 g_variant_iter_free (iter);
2645 g_assert (g_variant_iter_next_value (iter) == NULL);
2646 g_variant_iter_free (iter);
2655 equal = tree_instance_check_gvariant (tree, value);
2656 g_variant_unref (value);
2663 test_container (void)
2669 tree = tree_instance_new (NULL, 3);
2670 value = g_variant_ref_sink (tree_instance_get_gvariant (tree));
2672 s1 = g_variant_print (value, TRUE);
2673 g_assert (tree_instance_check_gvariant (tree, value));
2675 g_variant_get_data (value);
2677 s2 = g_variant_print (value, TRUE);
2678 g_assert (tree_instance_check_gvariant (tree, value));
2680 g_assert_cmpstr (s1, ==, s2);
2682 if (g_variant_is_container (value))
2684 GVariantBuilder builder;
2690 g_variant_builder_init (&builder, G_VARIANT_TYPE_VARIANT);
2691 tree_instance_build_gvariant (tree, &builder, TRUE);
2692 built = g_variant_builder_end (&builder);
2693 g_variant_ref_sink (built);
2694 g_variant_get_data (built);
2695 val = g_variant_get_variant (built);
2697 s3 = g_variant_print (val, TRUE);
2698 g_assert_cmpstr (s1, ==, s3);
2700 g_variant_iter_init (&iter, built);
2701 g_assert (tree_instance_check_iter (tree, &iter));
2702 g_assert (g_variant_iter_next_value (&iter) == NULL);
2704 g_variant_unref (built);
2705 g_variant_unref (val);
2709 tree_instance_free (tree);
2710 g_variant_unref (value);
2718 const gchar invalid[] = "hello\xffworld";
2721 /* ensure that the test data is not valid utf8... */
2722 g_assert (!g_utf8_validate (invalid, -1, NULL));
2724 /* load the data untrusted */
2725 value = g_variant_new_from_data (G_VARIANT_TYPE_STRING,
2726 invalid, sizeof invalid,
2729 /* ensure that the problem is caught and we get valid UTF-8 */
2730 g_assert (g_utf8_validate (g_variant_get_string (value, NULL), -1, NULL));
2731 g_variant_unref (value);
2734 /* now load it trusted */
2735 value = g_variant_new_from_data (G_VARIANT_TYPE_STRING,
2736 invalid, sizeof invalid,
2739 /* ensure we get the invalid data (ie: make sure that time wasn't
2740 * wasted on validating data that was marked as trusted)
2742 g_assert (g_variant_get_string (value, NULL) == invalid);
2743 g_variant_unref (value);
2747 test_containers (void)
2751 for (i = 0; i < 100; i++)
2756 g_variant_type_info_assert_no_infos ();
2760 test_format_strings (void)
2765 g_assert (g_variant_format_string_scan ("i", NULL, &end) && *end == '\0');
2766 g_assert (g_variant_format_string_scan ("@i", NULL, &end) && *end == '\0');
2767 g_assert (g_variant_format_string_scan ("@ii", NULL, &end) && *end == 'i');
2768 g_assert (g_variant_format_string_scan ("^a&s", NULL, &end) && *end == '\0');
2769 g_assert (g_variant_format_string_scan ("(^as)", NULL, &end) &&
2771 g_assert (!g_variant_format_string_scan ("(^s)", NULL, &end));
2772 g_assert (!g_variant_format_string_scan ("(^a)", NULL, &end));
2773 g_assert (!g_variant_format_string_scan ("(z)", NULL, &end));
2774 g_assert (!g_variant_format_string_scan ("az", NULL, &end));
2775 g_assert (!g_variant_format_string_scan ("{**}", NULL, &end));
2776 g_assert (!g_variant_format_string_scan ("{@**}", NULL, &end));
2777 g_assert (g_variant_format_string_scan ("{@y*}", NULL, &end) &&
2779 g_assert (g_variant_format_string_scan ("{yv}", NULL, &end) &&
2781 g_assert (!g_variant_format_string_scan ("{&?v}", NULL, &end));
2782 g_assert (g_variant_format_string_scan ("{@?v}", NULL, &end) &&
2784 g_assert (!g_variant_format_string_scan ("{&@sv}", NULL, &end));
2785 g_assert (!g_variant_format_string_scan ("{@&sv}", NULL, &end));
2786 g_assert (g_variant_format_string_scan ("{&sv}", NULL, &end) &&
2788 g_assert (!g_variant_format_string_scan ("{vv}", NULL, &end));
2789 g_assert (!g_variant_format_string_scan ("{y}", NULL, &end));
2790 g_assert (!g_variant_format_string_scan ("{yyy}", NULL, &end));
2791 g_assert (!g_variant_format_string_scan ("{ya}", NULL, &end));
2792 g_assert (g_variant_format_string_scan ("&s", NULL, &end) && *end == '\0');
2793 g_assert (!g_variant_format_string_scan ("&as", NULL, &end));
2794 g_assert (!g_variant_format_string_scan ("@z", NULL, &end));
2795 g_assert (!g_variant_format_string_scan ("az", NULL, &end));
2796 g_assert (!g_variant_format_string_scan ("a&s", NULL, &end));
2798 type = g_variant_format_string_scan_type ("mm(@xy^a&s*?@?)", NULL, &end);
2799 g_assert (type && *end == '\0');
2800 g_assert (g_variant_type_equal (type, G_VARIANT_TYPE ("mm(xyas*?\?)")));
2801 g_variant_type_free (type);
2803 type = g_variant_format_string_scan_type ("mm(@xy^a&*?@?)", NULL, NULL);
2804 g_assert (type == NULL);
2808 exit_on_abort (int signal)
2814 do_failed_test (const gchar *pattern)
2816 if (g_test_trap_fork (1000000, G_TEST_TRAP_SILENCE_STDERR))
2818 signal (SIGABRT, exit_on_abort);
2822 g_test_trap_assert_failed ();
2823 g_test_trap_assert_stderr (pattern);
2829 test_invalid_varargs (void)
2831 if (do_failed_test ("*GVariant format string*"))
2833 g_variant_new ("z");
2837 if (do_failed_test ("*valid GVariant format string as a prefix*"))
2841 g_variant_new_va ("z", &end, NULL);
2845 if (do_failed_test ("*type of `q' but * has a type of `y'*"))
2847 g_variant_get (g_variant_new ("y", 'a'), "q");
2853 check_and_free (GVariant *value,
2856 gchar *valstr = g_variant_print (value, FALSE);
2857 g_assert_cmpstr (str, ==, valstr);
2858 g_variant_unref (value);
2866 GVariantBuilder array;
2868 g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
2869 g_variant_builder_add (&array, "{sv}", "size",
2870 g_variant_new ("(ii)", 800, 600));
2871 g_variant_builder_add (&array, "{sv}", "title",
2872 g_variant_new_string ("Test case"));
2873 g_variant_builder_add_value (&array,
2874 g_variant_new_dict_entry (g_variant_new_string ("temperature"),
2875 g_variant_new_variant (
2876 g_variant_new_double (37.5))));
2877 check_and_free (g_variant_new ("(ma{sv}m(a{sv})ma{sv}ii)",
2878 NULL, FALSE, NULL, &array, 7777, 8888),
2879 "(nothing, nothing, {'size': <(800, 600)>, "
2880 "'title': <'Test case'>, "
2881 "'temperature': <37.5>}, "
2884 check_and_free (g_variant_new ("(imimimmimmimmi)",
2891 "(123, nothing, 123, nothing, just nothing, 123)");
2893 check_and_free (g_variant_new ("(ybnixd)",
2894 'a', 1, 22, 33, (guint64) 44, 5.5),
2895 "(0x61, true, 22, 33, 44, 5.5)");
2897 check_and_free (g_variant_new ("(@y?*rv)",
2898 g_variant_new ("y", 'a'),
2899 g_variant_new ("y", 'b'),
2900 g_variant_new ("y", 'c'),
2901 g_variant_new ("(y)", 'd'),
2902 g_variant_new ("y", 'e')),
2903 "(0x61, 0x62, 0x63, (0x64,), <byte 0x65>)");
2907 GVariantBuilder array;
2914 g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
2915 for (i = 0; i < 100; i++)
2917 number = g_strdup_printf ("%d", i);
2918 g_variant_builder_add (&array, "s", number);
2922 value = g_variant_builder_end (&array);
2923 g_variant_iter_init (&iter, value);
2926 while (g_variant_iter_loop (&iter, "s", &number))
2928 gchar *check = g_strdup_printf ("%d", i++);
2929 g_assert_cmpstr (number, ==, check);
2932 g_assert (number == NULL);
2933 g_assert (i == 100);
2935 g_variant_unref (value);
2937 g_variant_builder_init (&array, G_VARIANT_TYPE_ARRAY);
2938 for (i = 0; i < 100; i++)
2939 g_variant_builder_add (&array, "mi", i % 2 == 0, i);
2940 value = g_variant_builder_end (&array);
2943 g_variant_iter_init (&iter, value);
2944 while (g_variant_iter_loop (&iter, "mi", NULL, &val))
2945 g_assert (val == i++ || val == 0);
2946 g_assert (i == 100);
2949 g_variant_iter_init (&iter, value);
2950 while (g_variant_iter_loop (&iter, "mi", &just, &val))
2957 g_assert (val == this);
2962 g_assert (val == 0);
2965 g_assert (i == 100);
2967 g_variant_unref (value);
2971 const gchar *strvector[] = {"/hello", "/world", NULL};
2972 const gchar *test_strs[] = {"/foo", "/bar", "/baz" };
2973 GVariantBuilder builder;
2974 GVariantIter *array;
2982 g_variant_builder_init (&builder, G_VARIANT_TYPE ("ao"));
2983 g_variant_builder_add (&builder, "o", "/foo");
2984 g_variant_builder_add (&builder, "o", "/bar");
2985 g_variant_builder_add (&builder, "o", "/baz");
2986 value = g_variant_new("(ao^ao^a&o)", &builder, strvector, strvector);
2987 g_variant_iter_init (&tuple, value);
2988 g_variant_iter_next (&tuple, "ao", &array);
2991 while (g_variant_iter_loop (array, "o", &str))
2992 g_assert_cmpstr (str, ==, test_strs[i++]);
2995 g_variant_iter_free (array);
2998 g_variant_iter_init (&tuple, value);
2999 g_variant_iter_next (&tuple, "ao", &array);
3002 while (g_variant_iter_loop (array, "&o", &str))
3003 g_assert_cmpstr (str, ==, test_strs[i++]);
3006 g_variant_iter_free (array);
3008 g_variant_iter_next (&tuple, "^a&o", &strv);
3009 g_variant_iter_next (&tuple, "^ao", &my_strv);
3011 g_assert_cmpstr (strv[0], ==, "/hello");
3012 g_assert_cmpstr (strv[1], ==, "/world");
3013 g_assert (strv[2] == NULL);
3014 g_assert_cmpstr (my_strv[0], ==, "/hello");
3015 g_assert_cmpstr (my_strv[1], ==, "/world");
3016 g_assert (my_strv[2] == NULL);
3018 g_variant_unref (value);
3019 g_strfreev (my_strv);
3024 const gchar *strvector[] = { "i", "ii", "iii", "iv", "v", "vi", NULL };
3025 GVariantBuilder builder;
3034 g_variant_builder_init (&builder, G_VARIANT_TYPE ("aag"));
3035 g_variant_builder_open (&builder, G_VARIANT_TYPE ("ag"));
3036 for (i = 0; i < 6; i++)
3038 g_variant_builder_add (&builder, "g", strvector[i]);
3040 g_variant_builder_add (&builder, "&g", strvector[i]);
3041 g_variant_builder_close (&builder);
3042 g_variant_builder_add (&builder, "^ag", strvector);
3043 g_variant_builder_add (&builder, "^ag", strvector);
3044 value = g_variant_new ("aag", &builder);
3046 g_variant_iter_init (&iter, value);
3047 while (g_variant_iter_loop (&iter, "^ag", &strv))
3048 for (i = 0; i < 6; i++)
3049 g_assert_cmpstr (strv[i], ==, strvector[i]);
3051 g_variant_iter_init (&iter, value);
3052 while (g_variant_iter_loop (&iter, "^a&g", &strv))
3053 for (i = 0; i < 6; i++)
3054 g_assert_cmpstr (strv[i], ==, strvector[i]);
3056 g_variant_iter_init (&iter, value);
3057 while (g_variant_iter_loop (&iter, "ag", &i2))
3062 while (g_variant_iter_loop (i2, "g", &str))
3063 g_assert_cmpstr (str, ==, strvector[i++]);
3067 g_variant_iter_init (&iter, value);
3068 i3 = g_variant_iter_copy (&iter);
3069 while (g_variant_iter_loop (&iter, "@ag", &sub))
3071 gchar *str = g_variant_print (sub, TRUE);
3072 g_assert_cmpstr (str, ==,
3073 "[signature 'i', 'ii', 'iii', 'iv', 'v', 'vi']");
3077 if (do_failed_test ("*NULL has already been returned*"))
3079 g_variant_iter_next_value (&iter);
3084 while (g_variant_iter_loop (i3, "*", &sub))
3086 gchar *str = g_variant_print (sub, TRUE);
3087 g_assert_cmpstr (str, ==,
3088 "[signature 'i', 'ii', 'iii', 'iv', 'v', 'vi']");
3092 g_variant_iter_free (i3);
3094 for (i = 0; i < g_variant_n_children (value); i++)
3098 g_variant_get_child (value, i, "*", &sub);
3100 for (j = 0; j < g_variant_n_children (sub); j++)
3102 const gchar *str = NULL;
3105 g_variant_get_child (sub, j, "&g", &str);
3106 g_assert_cmpstr (str, ==, strvector[j]);
3108 cval = g_variant_get_child_value (sub, j);
3109 g_variant_get (cval, "&g", &str);
3110 g_assert_cmpstr (str, ==, strvector[j]);
3111 g_variant_unref (cval);
3114 g_variant_unref (sub);
3117 g_variant_unref (value);
3136 /* test all 'nothing' */
3137 value = g_variant_new ("(mymbmnmqmimumxmtmhmdmv)",
3140 FALSE, (gint16) 123,
3141 FALSE, (guint16) 123,
3142 FALSE, (gint32) 123,
3143 FALSE, (guint32) 123,
3144 FALSE, (gint64) 123,
3145 FALSE, (guint64) 123,
3147 FALSE, (gdouble) 37.5,
3151 g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3165 memset (justs, 1, sizeof justs);
3166 g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3178 g_assert (!(justs[0] || justs[1] || justs[2] || justs[3] || justs[4] ||
3179 justs[5] || justs[6] || justs[7] || justs[8] || justs[9]));
3182 memset (justs, 1, sizeof justs);
3183 byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3187 g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3188 &justs[0], &byteval,
3199 g_assert (!(justs[0] || justs[1] || justs[2] || justs[3] || justs[4] ||
3200 justs[5] || justs[6] || justs[7] || justs[8] || justs[9]));
3201 g_assert (byteval == '\0' && bval == FALSE);
3202 g_assert (i16val == 0 && u16val == 0 && i32val == 0 &&
3203 u32val == 0 && i64val == 0 && u64val == 0 &&
3204 hval == 0 && dval == 0.0);
3205 g_assert (vval == NULL);
3208 byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3212 g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3224 g_assert (byteval == '\0' && bval == FALSE);
3225 g_assert (i16val == 0 && u16val == 0 && i32val == 0 &&
3226 u32val == 0 && i64val == 0 && u64val == 0 &&
3227 hval == 0 && dval == 0.0);
3228 g_assert (vval == NULL);
3230 g_variant_unref (value);
3233 /* test all 'just' */
3234 value = g_variant_new ("(mymbmnmqmimumxmtmhmdmv)",
3238 TRUE, (guint16) 123,
3240 TRUE, (guint32) 123,
3242 TRUE, (guint64) 123,
3244 TRUE, (gdouble) 37.5,
3245 g_variant_new ("()"));
3248 g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3262 memset (justs, 0, sizeof justs);
3263 g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3275 g_assert (justs[0] && justs[1] && justs[2] && justs[3] && justs[4] &&
3276 justs[5] && justs[6] && justs[7] && justs[8] && justs[9]);
3279 memset (justs, 0, sizeof justs);
3280 byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3284 g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3285 &justs[0], &byteval,
3296 g_assert (justs[0] && justs[1] && justs[2] && justs[3] && justs[4] &&
3297 justs[5] && justs[6] && justs[7] && justs[8] && justs[9]);
3298 g_assert (byteval == 'a' && bval == TRUE);
3299 g_assert (i16val == 123 && u16val == 123 && i32val == 123 &&
3300 u32val == 123 && i64val == 123 && u64val == 123 &&
3301 hval == -1 && dval == 37.5);
3302 g_assert (g_variant_is_of_type (vval, G_VARIANT_TYPE_UNIT));
3303 g_variant_unref (vval);
3306 byteval = i16val = u16val = i32val = u32val = i64val = u64val = hval = 88;
3310 g_variant_get (value, "(mymbmnmqmimumxmtmhmdmv)",
3322 g_assert (byteval == 'a' && bval == TRUE);
3323 g_assert (i16val == 123 && u16val == 123 && i32val == 123 &&
3324 u32val == 123 && i64val == 123 && u64val == 123 &&
3325 hval == -1 && dval == 37.5);
3326 g_assert (g_variant_is_of_type (vval, G_VARIANT_TYPE_UNIT));
3327 g_variant_unref (vval);
3329 g_variant_unref (value);
3332 g_variant_type_info_assert_no_infos ();
3336 hash_get (GVariant *value,
3337 const gchar *format,
3340 const gchar *endptr = NULL;
3344 hash = g_str_has_suffix (format, "#");
3346 va_start (ap, format);
3347 g_variant_get_va (value, format, hash ? &endptr : NULL, &ap);
3351 g_assert (*endptr == '#');
3355 hash_new (const gchar *format,
3358 const gchar *endptr = NULL;
3363 hash = g_str_has_suffix (format, "#");
3365 va_start (ap, format);
3366 value = g_variant_new_va (format, hash ? &endptr : NULL, &ap);
3370 g_assert (*endptr == '#');
3382 value = hash_new ("i", 234);
3383 hash_get (value, "i", &x);
3384 g_assert (x == 234);
3385 g_variant_unref (value);
3388 value = hash_new ("i#", 234);
3389 hash_get (value, "i#", &x);
3390 g_assert (x == 234);
3391 g_variant_unref (value);
3393 g_variant_type_info_assert_no_infos ();
3397 test_builder_memory (void)
3399 GVariantBuilder *hb;
3402 hb = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
3403 g_variant_builder_open (hb, G_VARIANT_TYPE_ARRAY);
3404 g_variant_builder_open (hb, G_VARIANT_TYPE_ARRAY);
3405 g_variant_builder_open (hb, G_VARIANT_TYPE_ARRAY);
3406 g_variant_builder_add (hb, "s", "some value");
3407 g_variant_builder_ref (hb);
3408 g_variant_builder_unref (hb);
3409 g_variant_builder_unref (hb);
3411 hb = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
3412 g_variant_builder_unref (hb);
3414 hb = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
3415 g_variant_builder_clear (hb);
3416 g_variant_builder_unref (hb);
3418 g_variant_builder_init (&sb, G_VARIANT_TYPE_ARRAY);
3419 g_variant_builder_open (&sb, G_VARIANT_TYPE_ARRAY);
3420 g_variant_builder_open (&sb, G_VARIANT_TYPE_ARRAY);
3421 g_variant_builder_add (&sb, "s", "some value");
3422 g_variant_builder_clear (&sb);
3424 g_variant_type_info_assert_no_infos ();
3430 GVariant *items[4096];
3434 table = g_hash_table_new_full (g_variant_hash, g_variant_equal,
3435 (GDestroyNotify ) g_variant_unref,
3438 for (i = 0; i < G_N_ELEMENTS (items); i++)
3444 tree = tree_instance_new (NULL, 0);
3445 items[i] = tree_instance_get_gvariant (tree);
3446 tree_instance_free (tree);
3448 for (j = 0; j < i; j++)
3449 if (g_variant_equal (items[i], items[j]))
3451 g_variant_unref (items[i]);
3455 g_hash_table_insert (table,
3456 g_variant_ref_sink (items[i]),
3457 GINT_TO_POINTER (i));
3460 for (i = 0; i < G_N_ELEMENTS (items); i++)
3464 result = g_hash_table_lookup (table, items[i]);
3465 g_assert_cmpint (GPOINTER_TO_INT (result), ==, i);
3468 g_hash_table_unref (table);
3470 g_variant_type_info_assert_no_infos ();
3476 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
3477 # define native16(x) x, 0
3478 # define swapped16(x) 0, x
3480 # define native16(x) 0, x
3481 # define swapped16(x) x, 0
3483 /* all kinds of of crazy randomised testing already performed on the
3484 * byteswapper in the /gvariant/serialiser/byteswap test and all kinds
3485 * of crazy randomised testing performed against the serialiser
3486 * normalisation functions in the /gvariant/serialiser/fuzz/ tests.
3488 * just test a few simple cases here to make sure they each work
3490 guchar valid_data[] = { 'a', '\0', swapped16(66), 2,
3492 'b', '\0', swapped16(77), 2,
3494 guchar corrupt_data[] = { 'a', '\0', swapped16(66), 2,
3496 'b', '\0', swapped16(77), 2,
3498 GVariant *value, *swapped;
3499 gchar *string, *string2;
3503 value = g_variant_new_from_data (G_VARIANT_TYPE ("a(sn)"),
3504 valid_data, sizeof valid_data, TRUE,
3506 swapped = g_variant_byteswap (value);
3507 g_variant_unref (value);
3508 g_assert (g_variant_get_size (swapped) == 13);
3509 string = g_variant_print (swapped, FALSE);
3510 g_variant_unref (swapped);
3511 g_assert_cmpstr (string, ==, "[('a', 66), ('b', 77)]");
3514 /* untrusted but valid */
3515 value = g_variant_new_from_data (G_VARIANT_TYPE ("a(sn)"),
3516 valid_data, sizeof valid_data, FALSE,
3518 swapped = g_variant_byteswap (value);
3519 g_variant_unref (value);
3520 g_assert (g_variant_get_size (swapped) == 13);
3521 string = g_variant_print (swapped, FALSE);
3522 g_variant_unref (swapped);
3523 g_assert_cmpstr (string, ==, "[('a', 66), ('b', 77)]");
3526 /* untrusted, invalid */
3527 value = g_variant_new_from_data (G_VARIANT_TYPE ("a(sn)"),
3528 corrupt_data, sizeof corrupt_data, FALSE,
3530 string = g_variant_print (value, FALSE);
3531 swapped = g_variant_byteswap (value);
3532 g_variant_unref (value);
3533 g_assert (g_variant_get_size (swapped) == 13);
3534 value = g_variant_byteswap (swapped);
3535 g_variant_unref (swapped);
3536 string2 = g_variant_print (value, FALSE);
3537 g_assert (g_variant_get_size (value) == 13);
3538 g_variant_unref (value);
3539 g_assert_cmpstr (string, ==, string2);
3553 tree = tree_instance_new (NULL, 3);
3554 value = tree_instance_get_gvariant (tree);
3555 tree_instance_free (tree);
3557 pt = g_variant_print (value, TRUE);
3558 p = g_variant_print (value, FALSE);
3560 parsed = g_variant_parse (NULL, pt, NULL, NULL, NULL);
3561 res = g_variant_print (parsed, FALSE);
3562 g_assert_cmpstr (p, ==, res);
3563 g_variant_unref (parsed);
3566 parsed = g_variant_parse (g_variant_get_type (value), p,
3568 res = g_variant_print (parsed, TRUE);
3569 g_assert_cmpstr (pt, ==, res);
3570 g_variant_unref (parsed);
3573 g_variant_unref (value);
3583 for (i = 0; i < 100; i++)
3594 for (i = 0; i < 256; i++)
3597 val = g_variant_new_string (str);
3598 p = g_variant_print (val, FALSE);
3599 g_variant_unref (val);
3601 val = g_variant_parse (NULL, p, NULL, NULL, NULL);
3602 p2 = g_variant_print (val, FALSE);
3604 g_assert_cmpstr (str, ==, g_variant_get_string (val, NULL));
3605 g_assert_cmpstr (p, ==, p2);
3607 g_variant_unref (val);
3612 /* another mini test */
3617 value = g_variant_parse (G_VARIANT_TYPE_INT32, "1 2 3", NULL, &end, NULL);
3618 g_assert_cmpint (g_variant_get_int32 (value), ==, 1);
3619 /* make sure endptr returning works */
3620 g_assert_cmpstr (end, ==, " 2 3");
3621 g_variant_unref (value);
3624 g_variant_type_info_assert_no_infos ();
3628 test_parse_failures (void)
3630 const gchar *test[] = {
3631 "[1, 2,", "6:", "expected value",
3632 "", "0:", "expected value",
3633 "(1, 2,", "6:", "expected value",
3634 "<1", "2:", "expected `>'",
3635 "[]", "0-2:", "unable to infer",
3636 "(,", "1:", "expected value",
3637 "[4,'']", "1-2,3-5:", "common type",
3638 "[4, '', 5]", "1-2,4-6:", "common type",
3639 "['', 4, 5]", "1-3,5-6:", "common type",
3640 "[4, 5, '']", "1-2,7-9:", "common type",
3641 "[[4], [], ['']]", "1-4,10-14:", "common type",
3642 "[[], [4], ['']]", "5-8,10-14:", "common type",
3643 "just", "4:", "expected value",
3644 "nothing", "0-7:", "unable to infer",
3645 "just [4, '']", "6-7,9-11:", "common type",
3646 "[[4,'']]", "2-3,4-6:", "common type",
3647 "([4,''],)", "2-3,4-6:", "common type",
3649 "{}", "0-2:", "unable to infer",
3650 "{[1,2],[3,4]}", "0-13:", "basic types",
3651 "{[1,2]:[3,4]}", "0-13:", "basic types",
3652 "justt", "0-5:", "unknown keyword",
3653 "nothng", "0-6:", "unknown keyword",
3654 "uint33", "0-6:", "unknown keyword",
3655 "@mi just ''", "9-11:", "can not parse as",
3656 "@ai ['']", "5-7:", "can not parse as",
3657 "@(i) ('',)", "6-8:", "can not parse as",
3658 "[[], 5]", "1-3,5-6:", "common type",
3659 "[[5], 5]", "1-4,6-7:", "common type",
3660 "5 5", "2:", "expected end of input",
3661 "[5, [5, '']]", "5-6,8-10:", "common type",
3662 "@i just 5", "3-9:", "can not parse as",
3663 "@i nothing", "3-10:", "can not parse as",
3664 "@i []", "3-5:", "can not parse as",
3665 "@i ()", "3-5:", "can not parse as",
3666 "@ai (4,)", "4-8:", "can not parse as",
3667 "@(i) []", "5-7:", "can not parse as",
3668 "(5 5)", "3:", "expected `,'",
3669 "[5 5]", "3:", "expected `,' or `]'",
3670 "(5, 5 5)", "6:", "expected `,' or `)'",
3671 "[5, 5 5]", "6:", "expected `,' or `]'",
3672 "<@i []>", "4-6:", "can not parse as",
3673 "<[5 5]>", "4:", "expected `,' or `]'",
3674 "{[4,''],5}", "2-3,4-6:", "common type",
3675 "{5,[4,'']}", "4-5,6-8:", "common type",
3676 "@i {1,2}", "3-8:", "can not parse as",
3677 "{@i '', 5}", "4-6:", "can not parse as",
3678 "{5, @i ''}", "7-9:", "can not parse as",
3679 "@ai {}", "4-6:", "can not parse as",
3680 "{@i '': 5}", "4-6:", "can not parse as",
3681 "{5: @i ''}", "7-9:", "can not parse as",
3682 "{<4,5}", "3:", "expected `>'",
3683 "{4,<5}", "5:", "expected `>'",
3684 "{4,5,6}", "4:", "expected `}'",
3685 "{5 5}", "3:", "expected `:' or `,'",
3686 "{4: 5: 6}", "5:", "expected `,' or `}'",
3687 "{4:5,<6:7}", "7:", "expected `>'",
3688 "{4:5,6:<7}", "9:", "expected `>'",
3689 "{4:5,6 7}", "7:", "expected `:'",
3690 "@o 'foo'", "3-8:", "object path",
3691 "@g 'zzz'", "3-8:", "signature",
3692 "@i true", "3-7:", "can not parse as",
3693 "@z 4", "0-2:", "invalid type",
3694 "@a* []", "0-3:", "definite",
3695 "@ai [3 3]", "7:", "expected `,' or `]'",
3696 "18446744073709551616", "0-20:", "too big for any type",
3697 "-18446744073709551616", "0-21:", "too big for any type",
3698 "byte 256", "5-8:", "out of range for type",
3699 "byte -1", "5-7:", "out of range for type",
3700 "int16 32768", "6-11:", "out of range for type",
3701 "int16 -32769", "6-12:", "out of range for type",
3702 "uint16 -1", "7-9:", "out of range for type",
3703 "uint16 65536", "7-12:", "out of range for type",
3704 "2147483648", "0-10:", "out of range for type",
3705 "-2147483649", "0-11:", "out of range for type",
3706 "uint32 -1", "7-9:", "out of range for type",
3707 "uint32 4294967296", "7-17:", "out of range for type",
3708 "@x 9223372036854775808", "3-22:", "out of range for type",
3709 "@x -9223372036854775809", "3-23:", "out of range for type",
3710 "@t -1", "3-5:", "out of range for type",
3711 "@t 18446744073709551616", "3-23:", "too big for any type",
3712 "handle 2147483648", "7-17:", "out of range for type",
3713 "handle -2147483649", "7-18:", "out of range for type",
3714 "1.798e308", "0-9:", "too big for any type",
3715 "37.5a488", "4-5:", "invalid character",
3716 "0x7ffgf", "5-6:", "invalid character",
3717 "07758", "4-5:", "invalid character",
3718 "123a5", "3-4:", "invalid character",
3719 "@ai 123", "4-7:", "can not parse as",
3720 "'\"\\'", "0-4:", "unterminated string",
3721 "'\"\\'\\", "0-5:", "unterminated string",
3722 "boolean 4", "8-9:", "can not parse as",
3723 "int32 true", "6-10:", "can not parse as",
3724 "[double 5, int32 5]", "1-9,11-18:", "common type",
3725 "string 4", "7-8:", "can not parse as"
3729 for (i = 0; i < G_N_ELEMENTS (test); i += 3)
3731 GError *error = NULL;
3734 value = g_variant_parse (NULL, test[i], NULL, NULL, &error);
3735 g_assert (value == NULL);
3737 if (!strstr (error->message, test[i+2]))
3738 g_error ("test %d: Can't find `%s' in `%s'", i / 3,
3739 test[i+2], error->message);
3741 if (!g_str_has_prefix (error->message, test[i+1]))
3742 g_error ("test %d: Expected location `%s' in `%s'", i / 3,
3743 test[i+1], error->message);
3745 g_error_free (error);
3750 test_parse_positional (void)
3753 check_and_free (g_variant_new_parsed ("[('one', 1), (%s, 2),"
3754 " ('three', %i)]", "two", 3),
3755 "[('one', 1), ('two', 2), ('three', 3)]");
3756 value = g_variant_new_parsed ("[('one', 1), (%s, 2),"
3757 " ('three', %u)]", "two", 3);
3758 g_assert (g_variant_is_of_type (value, G_VARIANT_TYPE ("a(su)")));
3759 check_and_free (value, "[('one', 1), ('two', 2), ('three', 3)]");
3760 check_and_free (g_variant_new_parsed ("{%s:%i}", "one", 1), "{'one': 1}");
3762 if (do_failed_test ("*GVariant format string*"))
3764 g_variant_new_parsed ("%z");
3768 if (do_failed_test ("*can not parse as*"))
3770 g_variant_new_parsed ("uint32 %i", 2);
3774 if (do_failed_test ("*expected GVariant of type `i'*"))
3776 g_variant_new_parsed ("%@i", g_variant_new_uint32 (2));
3782 main (int argc, char **argv)
3786 g_test_init (&argc, &argv, NULL);
3788 g_test_add_func ("/gvariant/type", test_gvarianttype);
3789 g_test_add_func ("/gvariant/typeinfo", test_gvarianttypeinfo);
3790 g_test_add_func ("/gvariant/serialiser/maybe", test_maybes);
3791 g_test_add_func ("/gvariant/serialiser/array", test_arrays);
3792 g_test_add_func ("/gvariant/serialiser/tuple", test_tuples);
3793 g_test_add_func ("/gvariant/serialiser/variant", test_variants);
3794 g_test_add_func ("/gvariant/serialiser/strings", test_strings);
3795 g_test_add_func ("/gvariant/serialiser/byteswap", test_byteswaps);
3797 for (i = 1; i <= 20; i += 4)
3801 testname = g_strdup_printf ("/gvariant/serialiser/fuzz/%d%%", i);
3802 g_test_add_data_func (testname, GINT_TO_POINTER (i),
3803 (gpointer) test_fuzzes);
3807 g_test_add_func ("/gvariant/utf8", test_utf8);
3808 g_test_add_func ("/gvariant/containers", test_containers);
3809 g_test_add_func ("/gvariant/format-strings", test_format_strings);
3810 g_test_add_func ("/gvariant/invalid-varargs", test_invalid_varargs);
3811 g_test_add_func ("/gvariant/varargs", test_varargs);
3812 g_test_add_func ("/gvariant/valist", test_valist);
3813 g_test_add_func ("/gvariant/builder-memory", test_builder_memory);
3814 g_test_add_func ("/gvariant/hashing", test_hashing);
3815 g_test_add_func ("/gvariant/byteswap", test_gv_byteswap);
3816 g_test_add_func ("/gvariant/parser", test_parses);
3817 g_test_add_func ("/gvariant/parse-failures", test_parse_failures);
3818 g_test_add_func ("/gvariant/parse-positional", test_parse_positional);
3820 return g_test_run ();