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>
17 #define BASIC "bynqiuxthdsog?"
18 #define N_BASIC (G_N_ELEMENTS (BASIC) - 1)
20 #define INVALIDS "cefjklpwz&@^$"
21 #define N_INVALIDS (G_N_ELEMENTS (INVALIDS) - 1)
24 randomly (gdouble prob)
26 return g_test_rand_double_range (0, 1) < prob;
31 append_tuple_type_string (GString *, GString *, gboolean, gint);
33 /* append a random GVariantType to a GString
34 * append a description of the type to another GString
35 * return what the type is
38 append_type_string (GString *string,
43 if (!depth-- || randomly (0.3))
45 gchar b = BASIC[g_test_rand_int_range (0, N_BASIC - definite)];
46 g_string_append_c (string, b);
47 g_string_append_c (description, b);
52 return g_variant_type_copy (G_VARIANT_TYPE_BOOLEAN);
54 return g_variant_type_copy (G_VARIANT_TYPE_BYTE);
56 return g_variant_type_copy (G_VARIANT_TYPE_INT16);
58 return g_variant_type_copy (G_VARIANT_TYPE_UINT16);
60 return g_variant_type_copy (G_VARIANT_TYPE_INT32);
62 return g_variant_type_copy (G_VARIANT_TYPE_UINT32);
64 return g_variant_type_copy (G_VARIANT_TYPE_INT64);
66 return g_variant_type_copy (G_VARIANT_TYPE_UINT64);
68 return g_variant_type_copy (G_VARIANT_TYPE_HANDLE);
70 return g_variant_type_copy (G_VARIANT_TYPE_DOUBLE);
72 return g_variant_type_copy (G_VARIANT_TYPE_STRING);
74 return g_variant_type_copy (G_VARIANT_TYPE_OBJECT_PATH);
76 return g_variant_type_copy (G_VARIANT_TYPE_SIGNATURE);
78 return g_variant_type_copy (G_VARIANT_TYPE_BASIC);
80 g_assert_not_reached ();
87 switch (g_test_rand_int_range (0, definite ? 5 : 7))
91 GVariantType *element;
93 g_string_append_c (string, 'a');
94 g_string_append (description, "a of ");
95 element = append_type_string (string, description,
97 result = g_variant_type_new_array (element);
98 g_variant_type_free (element);
101 g_assert (g_variant_type_is_array (result));
106 GVariantType *element;
108 g_string_append_c (string, 'm');
109 g_string_append (description, "m of ");
110 element = append_type_string (string, description,
112 result = g_variant_type_new_maybe (element);
113 g_variant_type_free (element);
116 g_assert (g_variant_type_is_maybe (result));
120 result = append_tuple_type_string (string, description,
123 g_assert (g_variant_type_is_tuple (result));
128 GVariantType *key, *value;
130 g_string_append_c (string, '{');
131 g_string_append (description, "e of [");
132 key = append_type_string (string, description, definite, 0);
133 g_string_append (description, ", ");
134 value = append_type_string (string, description, definite, depth);
135 g_string_append_c (description, ']');
136 g_string_append_c (string, '}');
137 result = g_variant_type_new_dict_entry (key, value);
138 g_variant_type_free (key);
139 g_variant_type_free (value);
142 g_assert (g_variant_type_is_dict_entry (result));
146 g_string_append_c (string, 'v');
147 g_string_append_c (description, 'V');
148 result = g_variant_type_copy (G_VARIANT_TYPE_VARIANT);
149 g_assert (g_variant_type_equal (result, G_VARIANT_TYPE_VARIANT));
153 g_string_append_c (string, '*');
154 g_string_append_c (description, 'S');
155 result = g_variant_type_copy (G_VARIANT_TYPE_ANY);
156 g_assert (g_variant_type_equal (result, G_VARIANT_TYPE_ANY));
160 g_string_append_c (string, 'r');
161 g_string_append_c (description, 'R');
162 result = g_variant_type_copy (G_VARIANT_TYPE_TUPLE);
163 g_assert (g_variant_type_is_tuple (result));
167 g_assert_not_reached ();
174 static GVariantType *
175 append_tuple_type_string (GString *string,
176 GString *description,
180 GVariantType *result, *other_result;
181 GVariantType **types;
185 g_string_append_c (string, '(');
186 g_string_append (description, "t of [");
188 size = g_test_rand_int_range (0, 20);
189 types = g_new (GVariantType *, size + 1);
191 for (i = 0; i < size; i++)
193 types[i] = append_type_string (string, description, definite, depth);
196 g_string_append (description, ", ");
201 g_string_append_c (description, ']');
202 g_string_append_c (string, ')');
204 result = g_variant_type_new_tuple ((gpointer) types, size);
205 other_result = g_variant_type_new_tuple ((gpointer) types, -1);
206 g_assert (g_variant_type_equal (result, other_result));
207 g_variant_type_free (other_result);
208 for (i = 0; i < size; i++)
209 g_variant_type_free (types[i]);
215 /* given a valid type string, make it invalid */
217 invalid_mutation (const gchar *type_string)
219 gboolean have_parens, have_braces;
221 /* it's valid, so '(' implies ')' and same for '{' and '}' */
222 have_parens = strchr (type_string, '(') != NULL;
223 have_braces = strchr (type_string, '{') != NULL;
225 if (have_parens && have_braces && randomly (0.3))
227 /* swap a paren and a brace */
233 new = g_strdup (type_string);
243 /* count number of parens/braces */
244 while ((pp = strchr (pp + 1, p))) np++;
245 while ((bp = strchr (bp + 1, b))) nb++;
247 /* randomly pick one of each */
248 np = g_test_rand_int_range (0, np) + 1;
249 nb = g_test_rand_int_range (0, nb) + 1;
253 while (np--) pp = strchr (pp + 1, p);
254 while (nb--) bp = strchr (bp + 1, b);
257 g_assert (*bp == b && *pp == p);
264 if ((have_parens || have_braces) && randomly (0.3))
266 /* drop a paren/brace */
273 if (randomly (0.5)) p = '('; else p = ')';
275 if (randomly (0.5)) p = '{'; else p = '}';
277 new = g_strdup (type_string);
281 while ((pp = strchr (pp + 1, p))) np++;
282 np = g_test_rand_int_range (0, np) + 1;
284 while (np--) pp = strchr (pp + 1, p);
296 /* else, perform a random mutation at a random point */
304 /* insert a paren/brace */
306 if (randomly (0.5)) p = '('; else p = ')';
308 if (randomly (0.5)) p = '{'; else p = '}';
310 else if (randomly (0.5))
313 p = INVALIDS[g_test_rand_int_range (0, N_INVALIDS)];
322 length = strlen (type_string);
323 new = g_malloc (length + 2);
324 n = g_test_rand_int_range (0, length);
325 memcpy (new, type_string, n);
327 memcpy (new + n + 1, type_string + n, length - n);
328 new[length + 1] = '\0';
334 /* describe a type using the same language as is generated
335 * while generating the type with append_type_string
338 describe_type (const GVariantType *type)
342 if (g_variant_type_is_container (type))
344 g_assert (!g_variant_type_is_basic (type));
346 if (g_variant_type_is_array (type))
348 gchar *subtype = describe_type (g_variant_type_element (type));
349 result = g_strdup_printf ("a of %s", subtype);
352 else if (g_variant_type_is_maybe (type))
354 gchar *subtype = describe_type (g_variant_type_element (type));
355 result = g_strdup_printf ("m of %s", subtype);
358 else if (g_variant_type_is_tuple (type))
360 if (!g_variant_type_equal (type, G_VARIANT_TYPE_TUPLE))
362 const GVariantType *sub;
367 string = g_string_new ("t of [");
369 length = g_variant_type_n_items (type);
370 sub = g_variant_type_first (type);
371 for (i = 0; i < length; i++)
373 gchar *subtype = describe_type (sub);
374 g_string_append (string, subtype);
377 if ((sub = g_variant_type_next (sub)))
378 g_string_append (string, ", ");
380 g_assert (sub == NULL);
381 g_string_append_c (string, ']');
383 result = g_string_free (string, FALSE);
386 result = g_strdup ("R");
388 else if (g_variant_type_is_dict_entry (type))
390 gchar *key, *value, *key2, *value2;
392 key = describe_type (g_variant_type_key (type));
393 value = describe_type (g_variant_type_value (type));
394 key2 = describe_type (g_variant_type_first (type));
395 value2 = describe_type (
396 g_variant_type_next (g_variant_type_first (type)));
397 g_assert (g_variant_type_next (g_variant_type_next (
398 g_variant_type_first (type))) == NULL);
399 g_assert_cmpstr (key, ==, key2);
400 g_assert_cmpstr (value, ==, value2);
401 result = g_strjoin ("", "e of [", key, ", ", value, "]", NULL);
407 else if (g_variant_type_equal (type, G_VARIANT_TYPE_VARIANT))
409 result = g_strdup ("V");
412 g_assert_not_reached ();
416 if (g_variant_type_is_definite (type))
418 g_assert (g_variant_type_is_basic (type));
420 if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN))
421 result = g_strdup ("b");
422 else if (g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
423 result = g_strdup ("y");
424 else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT16))
425 result = g_strdup ("n");
426 else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT16))
427 result = g_strdup ("q");
428 else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32))
429 result = g_strdup ("i");
430 else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT32))
431 result = g_strdup ("u");
432 else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT64))
433 result = g_strdup ("x");
434 else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT64))
435 result = g_strdup ("t");
436 else if (g_variant_type_equal (type, G_VARIANT_TYPE_HANDLE))
437 result = g_strdup ("h");
438 else if (g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
439 result = g_strdup ("d");
440 else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING))
441 result = g_strdup ("s");
442 else if (g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH))
443 result = g_strdup ("o");
444 else if (g_variant_type_equal (type, G_VARIANT_TYPE_SIGNATURE))
445 result = g_strdup ("g");
447 g_assert_not_reached ();
451 if (g_variant_type_equal (type, G_VARIANT_TYPE_ANY))
453 result = g_strdup ("S");
455 else if (g_variant_type_equal (type, G_VARIANT_TYPE_BASIC))
457 result = g_strdup ("?");
460 g_assert_not_reached ();
467 /* given a type string, replace one of the indefinite type characters in
468 * it with a matching type (possibly the same type).
471 generate_subtype (const gchar *type_string)
473 GVariantType *replacement;
474 GString *result, *junk;
475 gint length, n = 0, l;
477 result = g_string_new (NULL);
478 junk = g_string_new (NULL);
480 /* count the number of indefinite type characters */
481 for (length = 0; type_string[length]; length++)
482 n += type_string[length] == 'r' ||
483 type_string[length] == '?' ||
484 type_string[length] == '*';
485 /* length now is strlen (type_string) */
487 /* pick one at random to replace */
488 n = g_test_rand_int_range (0, n) + 1;
492 while (n--) l += strcspn (type_string + l + 1, "r?*") + 1;
493 g_assert (type_string[l] == 'r' ||
494 type_string[l] == '?' ||
495 type_string[l] == '*');
497 /* store up to that point in a GString */
498 g_string_append_len (result, type_string, l);
500 /* then store the replacement in the GString */
501 if (type_string[l] == 'r')
502 replacement = append_tuple_type_string (result, junk, FALSE, 3);
504 else if (type_string[l] == '?')
505 replacement = append_type_string (result, junk, FALSE, 0);
507 else if (type_string[l] == '*')
508 replacement = append_type_string (result, junk, FALSE, 3);
511 g_assert_not_reached ();
513 /* ensure the replacement has the proper type */
514 g_assert (g_variant_type_is_subtype_of (replacement,
515 (gpointer) &type_string[l]));
517 /* store the rest from the original type string */
518 g_string_append (result, type_string + l + 1);
520 g_variant_type_free (replacement);
521 g_string_free (junk, TRUE);
523 return g_string_free (result, FALSE);
528 const GVariantType *type;
529 struct typestack *parent;
532 /* given an indefinite type string, replace one of the indefinite
533 * characters in it with a matching type and ensure that the result is a
534 * subtype of the original. repeat.
537 subtype_check (const gchar *type_string,
538 struct typestack *parent_ts)
540 struct typestack ts, *node;
544 subtype = generate_subtype (type_string);
546 ts.type = G_VARIANT_TYPE (subtype);
547 ts.parent = parent_ts;
549 for (node = &ts; node; node = node->parent)
551 /* this type should be a subtype of each parent type */
552 g_assert (g_variant_type_is_subtype_of (ts.type, node->type));
554 /* it should only be a supertype when it is exactly equal */
555 g_assert (g_variant_type_is_subtype_of (node->type, ts.type) ==
556 g_variant_type_equal (ts.type, node->type));
561 if (!g_variant_type_is_definite (ts.type) && depth < 5)
563 /* the type is still indefinite and we haven't repeated too many
564 * times. go once more.
567 subtype_check (subtype, &ts);
574 test_gvarianttype (void)
578 for (i = 0; i < 2000; i++)
580 GString *type_string, *description;
581 GVariantType *type, *other_type;
582 const GVariantType *ctype;
586 type_string = g_string_new (NULL);
587 description = g_string_new (NULL);
589 /* generate a random type, its type string and a description
591 * exercises type constructor functions and g_variant_type_copy()
593 type = append_type_string (type_string, description, FALSE, 6);
595 /* convert the type string to a type and ensure that it is equal
596 * to the one produced with the type constructor routines
598 ctype = G_VARIANT_TYPE (type_string->str);
599 g_assert (g_variant_type_equal (ctype, type));
600 g_assert (g_variant_type_is_subtype_of (ctype, type));
601 g_assert (g_variant_type_is_subtype_of (type, ctype));
603 /* check if the type is indefinite */
604 if (!g_variant_type_is_definite (type))
606 struct typestack ts = { type, NULL };
608 /* if it is indefinite, then replace one of the indefinite
609 * characters with a matching type and ensure that the result
610 * is a subtype of the original type. repeat.
612 subtype_check (type_string->str, &ts);
615 /* ensure that no indefinite characters appear */
616 g_assert (strcspn (type_string->str, "r?*") == type_string->len);
619 /* describe the type.
621 * exercises the type iterator interface
623 desc = describe_type (type);
625 /* make sure the description matches */
626 g_assert_cmpstr (desc, ==, description->str);
629 /* make an invalid mutation to the type and make sure the type
630 * validation routines catch it */
631 invalid = invalid_mutation (type_string->str);
632 g_assert (g_variant_type_string_is_valid (type_string->str));
633 g_assert (!g_variant_type_string_is_valid (invalid));
636 /* concatenate another type to the type string and ensure that
637 * the result is recognised as being invalid
639 other_type = append_type_string (type_string, description, FALSE, 2);
641 g_string_free (description, TRUE);
642 g_string_free (type_string, TRUE);
643 g_variant_type_free (other_type);
644 g_variant_type_free (type);
648 #undef G_GNUC_INTERNAL
649 #define G_GNUC_INTERNAL static
651 #define DISABLE_VISIBILITY
652 #define GLIB_COMPILATION
653 #include <glib/gvarianttypeinfo.c>
655 #define ALIGNED(x, y) (((x + (y - 1)) / y) * y)
657 /* do our own calculation of the fixed_size and alignment of a type
658 * using a simple algorithm to make sure the "fancy" one in the
659 * implementation is correct.
662 calculate_type_info (const GVariantType *type,
666 if (g_variant_type_is_array (type) ||
667 g_variant_type_is_maybe (type))
669 calculate_type_info (g_variant_type_element (type), NULL, alignment);
674 else if (g_variant_type_is_tuple (type) ||
675 g_variant_type_is_dict_entry (type))
677 if (g_variant_type_n_items (type))
679 const GVariantType *sub;
688 sub = g_variant_type_first (type);
694 calculate_type_info (sub, &this_fs, &this_al);
696 al = MAX (al, this_al);
706 size = ALIGNED (size, this_al);
710 while ((sub = g_variant_type_next (sub)));
712 size = ALIGNED (size, al);
733 if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN) ||
734 g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
739 else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT16) ||
740 g_variant_type_equal (type, G_VARIANT_TYPE_UINT16))
745 else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32) ||
746 g_variant_type_equal (type, G_VARIANT_TYPE_UINT32) ||
747 g_variant_type_equal (type, G_VARIANT_TYPE_HANDLE))
752 else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT64) ||
753 g_variant_type_equal (type, G_VARIANT_TYPE_UINT64) ||
754 g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
758 else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING) ||
759 g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH) ||
760 g_variant_type_equal (type, G_VARIANT_TYPE_SIGNATURE))
765 else if (g_variant_type_equal (type, G_VARIANT_TYPE_VARIANT))
771 g_assert_not_reached ();
781 /* same as the describe_type() function above, but iterates over
782 * typeinfo instead of types.
785 describe_info (GVariantTypeInfo *info)
789 switch (g_variant_type_info_get_type_char (info))
791 case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
795 element = describe_info (g_variant_type_info_element (info));
796 result = g_strdup_printf ("m of %s", element);
801 case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
805 element = describe_info (g_variant_type_info_element (info));
806 result = g_strdup_printf ("a of %s", element);
811 case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
813 const gchar *sep = "";
818 string = g_string_new ("t of [");
819 length = g_variant_type_info_n_members (info);
821 for (i = 0; i < length; i++)
823 const GVariantMemberInfo *minfo;
826 g_string_append (string, sep);
829 minfo = g_variant_type_info_member_info (info, i);
830 subtype = describe_info (minfo->type_info);
831 g_string_append (string, subtype);
835 g_string_append_c (string, ']');
837 result = g_string_free (string, FALSE);
841 case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
843 const GVariantMemberInfo *keyinfo, *valueinfo;
846 g_assert_cmpint (g_variant_type_info_n_members (info), ==, 2);
847 keyinfo = g_variant_type_info_member_info (info, 0);
848 valueinfo = g_variant_type_info_member_info (info, 1);
849 key = describe_info (keyinfo->type_info);
850 value = describe_info (valueinfo->type_info);
851 result = g_strjoin ("", "e of [", key, ", ", value, "]", NULL);
857 case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
858 result = g_strdup ("V");
862 result = g_strdup (g_variant_type_info_get_type_string (info));
863 g_assert_cmpint (strlen (result), ==, 1);
870 /* check that the O(1) method of calculating offsets meshes with the
871 * results of simple iteration.
874 check_offsets (GVariantTypeInfo *info,
875 const GVariantType *type)
880 length = g_variant_type_info_n_members (info);
881 g_assert_cmpint (length, ==, g_variant_type_n_items (type));
883 /* the 'flavour' is the low order bits of the ending point of
884 * variable-size items in the tuple. this lets us test that the type
885 * info is correct for various starting alignments.
887 for (flavour = 0; flavour < 8; flavour++)
889 const GVariantType *subtype;
890 gsize last_offset_index;
895 subtype = g_variant_type_first (type);
896 last_offset_index = -1;
900 /* go through the tuple, keeping track of our position */
901 for (i = 0; i < length; i++)
906 calculate_type_info (subtype, &fixed_size, &alignment);
908 position = ALIGNED (position, alignment);
910 /* compare our current aligned position (ie: the start of this
911 * item) to the start offset that would be calculated if we
915 const GVariantMemberInfo *member;
918 member = g_variant_type_info_member_info (info, i);
919 g_assert_cmpint (member->i, ==, last_offset_index);
921 /* do the calculation using the typeinfo */
927 /* did we reach the same spot? */
928 g_assert_cmpint (start, ==, position);
933 /* fixed size. add that size. */
934 position += fixed_size;
938 /* variable size. do the flavouring. */
939 while ((position & 0x7) != flavour)
942 /* and store the offset, just like it would be in the
945 last_offset = position;
950 subtype = g_variant_type_next (subtype);
953 /* make sure we used up exactly all the types */
954 g_assert (subtype == NULL);
959 test_gvarianttypeinfo (void)
963 for (i = 0; i < 2000; i++)
965 GString *type_string, *description;
966 gsize fixed_size1, fixed_size2;
967 guint alignment1, alignment2;
968 GVariantTypeInfo *info;
972 type_string = g_string_new (NULL);
973 description = g_string_new (NULL);
976 type = append_type_string (type_string, description, TRUE, 6);
978 /* create a typeinfo for it */
979 info = g_variant_type_info_get (type);
981 /* make sure the typeinfo has the right type string */
982 g_assert_cmpstr (g_variant_type_info_get_type_string (info), ==,
985 /* calculate the alignment and fixed size, compare to the
986 * typeinfo's calculations
988 calculate_type_info (type, &fixed_size1, &alignment1);
989 g_variant_type_info_query (info, &alignment2, &fixed_size2);
990 g_assert_cmpint (fixed_size1, ==, fixed_size2);
991 g_assert_cmpint (alignment1, ==, alignment2 + 1);
993 /* test the iteration functions over typeinfo structures by
994 * "describing" the typeinfo and verifying equality.
996 desc = describe_info (info);
997 g_assert_cmpstr (desc, ==, description->str);
999 /* do extra checks for containers */
1000 if (g_variant_type_is_array (type) ||
1001 g_variant_type_is_maybe (type))
1003 const GVariantType *element;
1007 element = g_variant_type_element (type);
1008 calculate_type_info (element, &efs1, &ea1);
1009 g_variant_type_info_query_element (info, &ea2, &efs2);
1010 g_assert_cmpint (efs1, ==, efs2);
1011 g_assert_cmpint (ea1, ==, ea2 + 1);
1013 g_assert_cmpint (ea1, ==, alignment1);
1014 g_assert_cmpint (0, ==, fixed_size1);
1016 else if (g_variant_type_is_tuple (type) ||
1017 g_variant_type_is_dict_entry (type))
1019 /* make sure the "magic constants" are working */
1020 check_offsets (info, type);
1023 g_string_free (type_string, TRUE);
1024 g_string_free (description, TRUE);
1025 g_variant_type_info_unref (info);
1026 g_variant_type_free (type);
1030 assert_no_type_infos ();
1033 #include <glib/gvariant-serialiser.c>
1035 #define MAX_FIXED_MULTIPLIER 256
1036 #define MAX_INSTANCE_SIZE 1024
1037 #define MAX_ARRAY_CHILDREN 128
1038 #define MAX_TUPLE_CHILDREN 128
1040 /* this function generates a random type such that all characteristics
1041 * that are "interesting" to the serialiser are tested.
1043 * this basically means:
1044 * - test different alignments
1045 * - test variable sized items and fixed sized items
1046 * - test different fixed sizes
1049 random_type_string (void)
1051 const guchar base_types[] = "ynix";
1054 base_type = base_types[g_test_rand_int_range (0, 4)];
1056 if (g_test_rand_bit ())
1057 /* construct a fixed-sized type */
1059 char type_string[MAX_FIXED_MULTIPLIER];
1063 multiplier = g_test_rand_int_range (1, sizeof type_string - 1);
1065 type_string[i++] = '(';
1066 while (multiplier--)
1067 type_string[i++] = base_type;
1068 type_string[i++] = ')';
1070 return g_strndup (type_string, i);
1073 /* construct a variable-sized type */
1075 char type_string[2] = { 'a', base_type };
1077 return g_strndup (type_string, 2);
1083 GVariantTypeInfo *type_info;
1086 gboolean is_fixed_sized;
1090 #define INSTANCE_MAGIC 1287582829
1094 static RandomInstance *
1095 random_instance (GVariantTypeInfo *type_info)
1097 RandomInstance *instance;
1099 instance = g_slice_new (RandomInstance);
1101 if (type_info == NULL)
1103 gchar *str = random_type_string ();
1104 instance->type_info = g_variant_type_info_get (G_VARIANT_TYPE (str));
1108 instance->type_info = g_variant_type_info_ref (type_info);
1110 instance->seed = g_test_rand_int ();
1112 g_variant_type_info_query (instance->type_info,
1113 &instance->alignment,
1116 instance->is_fixed_sized = instance->size != 0;
1118 if (!instance->is_fixed_sized)
1119 instance->size = g_test_rand_int_range (0, MAX_INSTANCE_SIZE);
1121 instance->magic = INSTANCE_MAGIC;
1127 random_instance_free (RandomInstance *instance)
1129 g_variant_type_info_unref (instance->type_info);
1130 g_slice_free (RandomInstance, instance);
1134 append_instance_size (RandomInstance *instance,
1137 *offset += (-*offset) & instance->alignment;
1138 *offset += instance->size;
1142 random_instance_write (RandomInstance *instance,
1148 g_assert_cmpint ((gsize) buffer & instance->alignment, ==, 0);
1150 rand = g_rand_new_with_seed (instance->seed);
1151 for (i = 0; i < instance->size; i++)
1152 buffer[i] = g_rand_int (rand);
1157 append_instance_data (RandomInstance *instance,
1160 while (((gsize) *buffer) & instance->alignment)
1161 *(*buffer)++ = '\0';
1163 random_instance_write (instance, *buffer);
1164 *buffer += instance->size;
1168 random_instance_assert (RandomInstance *instance,
1175 g_assert_cmpint ((gsize) buffer & instance->alignment, ==, 0);
1176 g_assert_cmpint (size, ==, instance->size);
1178 rand = g_rand_new_with_seed (instance->seed);
1179 for (i = 0; i < instance->size; i++)
1181 guchar byte = g_rand_int (rand);
1183 g_assert (buffer[i] == byte);
1187 return i == instance->size;
1191 random_instance_check (RandomInstance *instance,
1198 g_assert_cmpint ((gsize) buffer & instance->alignment, ==, 0);
1200 if (size != instance->size)
1203 rand = g_rand_new_with_seed (instance->seed);
1204 for (i = 0; i < instance->size; i++)
1205 if (buffer[i] != (guchar) g_rand_int (rand))
1209 return i == instance->size;
1213 random_instance_filler (GVariantSerialised *serialised,
1216 RandomInstance *instance = data;
1218 g_assert (instance->magic == INSTANCE_MAGIC);
1220 if (serialised->type_info == NULL)
1221 serialised->type_info = instance->type_info;
1223 if (serialised->size == 0)
1224 serialised->size = instance->size;
1226 g_assert (serialised->type_info == instance->type_info);
1227 g_assert (serialised->size == instance->size);
1229 if (serialised->data)
1230 random_instance_write (instance, serialised->data);
1234 calculate_offset_size (gsize body_size,
1240 if (body_size + n_offsets <= G_MAXUINT8)
1243 if (body_size + 2 * n_offsets <= G_MAXUINT16)
1246 if (body_size + 4 * n_offsets <= G_MAXUINT32)
1249 /* the test case won't generate anything bigger */
1250 g_assert_not_reached ();
1254 flavoured_malloc (gsize size, gsize flavour)
1256 g_assert (flavour < 8);
1261 return g_malloc (size + flavour) + flavour;
1265 flavoured_free (gpointer data)
1267 g_free ((gpointer) (((gsize) data) & ~7));
1271 append_offset (guchar **offset_ptr,
1277 guchar bytes[sizeof (gsize)];
1281 tmpvalue.integer = GSIZE_TO_LE (offset);
1282 memcpy (*offset_ptr, tmpvalue.bytes, offset_size);
1283 *offset_ptr += offset_size;
1287 prepend_offset (guchar **offset_ptr,
1293 guchar bytes[sizeof (gsize)];
1297 *offset_ptr -= offset_size;
1298 tmpvalue.integer = GSIZE_TO_LE (offset);
1299 memcpy (*offset_ptr, tmpvalue.bytes, offset_size);
1305 GVariantTypeInfo *type_info;
1306 RandomInstance *instance;
1310 instance = random_instance (NULL);
1313 const gchar *element;
1316 element = g_variant_type_info_get_type_string (instance->type_info);
1317 tmp = g_strdup_printf ("m%s", element);
1318 type_info = g_variant_type_info_get (G_VARIANT_TYPE (tmp));
1322 needed_size = g_variant_serialiser_needed_size (type_info,
1323 random_instance_filler,
1325 g_assert_cmpint (needed_size, ==, 0);
1327 needed_size = g_variant_serialiser_needed_size (type_info,
1328 random_instance_filler,
1329 (gpointer *) &instance, 1);
1331 if (instance->is_fixed_sized)
1332 g_assert_cmpint (needed_size, ==, instance->size);
1334 g_assert_cmpint (needed_size, ==, instance->size + 1);
1339 ptr = data = g_malloc (needed_size);
1340 append_instance_data (instance, &ptr);
1342 if (!instance->is_fixed_sized)
1345 g_assert_cmpint (ptr - data, ==, needed_size);
1352 alignment = instance->alignment + 1;
1354 for (flavour = 0; flavour < 8; flavour += alignment)
1356 GVariantSerialised serialised;
1357 GVariantSerialised child;
1359 serialised.type_info = type_info;
1360 serialised.data = flavoured_malloc (needed_size, flavour);
1361 serialised.size = needed_size;
1363 g_variant_serialiser_serialise (serialised,
1364 random_instance_filler,
1365 (gpointer *) &instance, 1);
1366 child = g_variant_serialised_get_child (serialised, 0);
1367 g_assert (child.type_info == instance->type_info);
1368 random_instance_assert (instance, child.data, child.size);
1369 g_variant_type_info_unref (child.type_info);
1370 flavoured_free (serialised.data);
1374 g_variant_type_info_unref (type_info);
1375 random_instance_free (instance);
1384 for (i = 0; i < 1000; i++)
1387 assert_no_type_infos ();
1393 GVariantTypeInfo *element_info;
1394 GVariantTypeInfo *array_info;
1395 RandomInstance **instances;
1402 gchar *element_type, *array_type;
1404 element_type = random_type_string ();
1405 array_type = g_strdup_printf ("a%s", element_type);
1407 element_info = g_variant_type_info_get (G_VARIANT_TYPE (element_type));
1408 array_info = g_variant_type_info_get (G_VARIANT_TYPE (array_type));
1409 g_assert (g_variant_type_info_element (array_info) == element_info);
1411 g_free (element_type);
1412 g_free (array_type);
1418 n_children = g_test_rand_int_range (0, MAX_ARRAY_CHILDREN);
1419 instances = g_new (RandomInstance *, n_children);
1420 for (i = 0; i < n_children; i++)
1421 instances[i] = random_instance (element_info);
1424 needed_size = g_variant_serialiser_needed_size (array_info,
1425 random_instance_filler,
1426 (gpointer *) instances,
1430 gsize element_fixed_size;
1431 gsize body_size = 0;
1434 for (i = 0; i < n_children; i++)
1435 append_instance_size (instances[i], &body_size);
1437 g_variant_type_info_query (element_info, NULL, &element_fixed_size);
1439 if (!element_fixed_size)
1441 offset_size = calculate_offset_size (body_size, n_children);
1443 if (offset_size == 0)
1449 g_assert_cmpint (needed_size, ==, body_size + n_children * offset_size);
1453 guchar *offset_ptr, *body_ptr;
1456 body_ptr = data = g_malloc (needed_size);
1457 offset_ptr = body_ptr + needed_size - offset_size * n_children;
1459 for (i = 0; i < n_children; i++)
1461 append_instance_data (instances[i], &body_ptr);
1462 append_offset (&offset_ptr, body_ptr - data, offset_size);
1465 g_assert (body_ptr == data + needed_size - offset_size * n_children);
1466 g_assert (offset_ptr == data + needed_size);
1474 g_variant_type_info_query (array_info, &alignment, NULL);
1477 for (flavour = 0; flavour < 8; flavour += alignment)
1479 GVariantSerialised serialised;
1481 serialised.type_info = array_info;
1482 serialised.data = flavoured_malloc (needed_size, flavour);
1483 serialised.size = needed_size;
1485 g_variant_serialiser_serialise (serialised, random_instance_filler,
1486 (gpointer *) instances, n_children);
1488 g_assert (memcmp (serialised.data, data, serialised.size) == 0);
1489 g_assert (g_variant_serialised_n_children (serialised) == n_children);
1491 for (i = 0; i < n_children; i++)
1493 GVariantSerialised child;
1495 child = g_variant_serialised_get_child (serialised, i);
1496 g_assert (child.type_info == instances[i]->type_info);
1497 random_instance_assert (instances[i], child.data, child.size);
1498 g_variant_type_info_unref (child.type_info);
1501 flavoured_free (serialised.data);
1508 for (i = 0; i < n_children; i++)
1509 random_instance_free (instances[i]);
1513 g_variant_type_info_unref (element_info);
1514 g_variant_type_info_unref (array_info);
1523 for (i = 0; i < 100; i++)
1526 assert_no_type_infos ();
1532 GVariantTypeInfo *type_info;
1533 RandomInstance **instances;
1534 gboolean fixed_size;
1541 n_children = g_test_rand_int_range (0, MAX_TUPLE_CHILDREN);
1542 instances = g_new (RandomInstance *, n_children);
1545 GString *type_string;
1551 type_string = g_string_new ("(");
1552 for (i = 0; i < n_children; i++)
1556 instances[i] = random_instance (NULL);
1558 alignment |= instances[i]->alignment;
1559 if (!instances[i]->is_fixed_sized)
1562 str = g_variant_type_info_get_type_string (instances[i]->type_info);
1563 g_string_append (type_string, str);
1565 g_string_append_c (type_string, ')');
1567 type_info = g_variant_type_info_get (G_VARIANT_TYPE (type_string->str));
1568 g_string_free (type_string, TRUE);
1571 needed_size = g_variant_serialiser_needed_size (type_info,
1572 random_instance_filler,
1573 (gpointer *) instances,
1576 gsize body_size = 0;
1580 for (i = 0; i < n_children; i++)
1582 append_instance_size (instances[i], &body_size);
1584 if (i != n_children - 1 && !instances[i]->is_fixed_sized)
1590 body_size += (-body_size) & alignment;
1592 g_assert ((body_size == 0) == (n_children == 0));
1593 if (n_children == 0)
1597 offset_size = calculate_offset_size (body_size, offsets);
1598 g_assert_cmpint (needed_size, ==, body_size + offsets * offset_size);
1606 body_ptr = data = g_malloc (needed_size);
1607 ofs_ptr = body_ptr + needed_size;
1609 for (i = 0; i < n_children; i++)
1611 append_instance_data (instances[i], &body_ptr);
1613 if (i != n_children - 1 && !instances[i]->is_fixed_sized)
1614 prepend_offset (&ofs_ptr, body_ptr - data, offset_size);
1619 while (((gsize) body_ptr) & alignment)
1622 g_assert ((body_ptr == data) == (n_children == 0));
1623 if (n_children == 0)
1629 g_assert (body_ptr == ofs_ptr);
1638 for (flavour = 0; flavour < 8; flavour += alignment)
1640 GVariantSerialised serialised;
1642 serialised.type_info = type_info;
1643 serialised.data = flavoured_malloc (needed_size, flavour);
1644 serialised.size = needed_size;
1646 g_variant_serialiser_serialise (serialised, random_instance_filler,
1647 (gpointer *) instances, n_children);
1649 g_assert (memcmp (serialised.data, data, serialised.size) == 0);
1650 g_assert (g_variant_serialised_n_children (serialised) == n_children);
1652 for (i = 0; i < n_children; i++)
1654 GVariantSerialised child;
1656 child = g_variant_serialised_get_child (serialised, i);
1657 g_assert (child.type_info == instances[i]->type_info);
1658 random_instance_assert (instances[i], child.data, child.size);
1659 g_variant_type_info_unref (child.type_info);
1662 flavoured_free (serialised.data);
1669 for (i = 0; i < n_children; i++)
1670 random_instance_free (instances[i]);
1674 g_variant_type_info_unref (type_info);
1683 for (i = 0; i < 100; i++)
1686 assert_no_type_infos ();
1692 GVariantTypeInfo *type_info;
1693 RandomInstance *instance;
1694 const gchar *type_string;
1699 type_info = g_variant_type_info_get (G_VARIANT_TYPE_VARIANT);
1700 instance = random_instance (NULL);
1702 type_string = g_variant_type_info_get_type_string (instance->type_info);
1703 len = strlen (type_string);
1705 needed_size = g_variant_serialiser_needed_size (type_info,
1706 random_instance_filler,
1707 (gpointer *) &instance, 1);
1709 g_assert_cmpint (needed_size, ==, instance->size + 1 + len);
1714 ptr = data = g_malloc (needed_size);
1715 append_instance_data (instance, &ptr);
1717 memcpy (ptr, type_string, len);
1720 g_assert (data + needed_size == ptr);
1724 /* variants are 8-aligned, so no extra flavouring */
1725 GVariantSerialised serialised;
1726 GVariantSerialised child;
1728 serialised.type_info = type_info;
1729 serialised.data = flavoured_malloc (needed_size, 0);
1730 serialised.size = needed_size;
1732 g_variant_serialiser_serialise (serialised, random_instance_filler,
1733 (gpointer *) &instance, 1);
1735 g_assert (memcmp (serialised.data, data, serialised.size) == 0);
1736 g_assert (g_variant_serialised_n_children (serialised) == 1);
1738 child = g_variant_serialised_get_child (serialised, 0);
1739 g_assert (child.type_info == instance->type_info);
1740 random_instance_check (instance, child.data, child.size);
1742 g_variant_type_info_unref (child.type_info);
1743 flavoured_free (serialised.data);
1746 g_variant_type_info_unref (type_info);
1747 random_instance_free (instance);
1752 test_variants (void)
1756 for (i = 0; i < 100; i++)
1759 assert_no_type_infos ();
1772 #define is_objpath is_string | 2
1773 #define is_sig is_string | 4
1775 { is_nval, 0, NULL },
1776 { is_string, 13, "hello world!" },
1777 { is_nval, 13, "hello world\0" },
1778 { is_nval, 13, "hello\0world!" },
1779 { is_nval, 12, "hello world!" },
1781 { is_objpath, 2, "/" },
1782 { is_objpath, 3, "/a" },
1783 { is_string, 3, "//" },
1784 { is_objpath, 11, "/some/path" },
1785 { is_string, 12, "/some/path/" },
1786 { is_nval, 11, "/some\0path" },
1787 { is_string, 11, "/some\\path" },
1788 { is_string, 12, "/some//path" },
1789 { is_string, 12, "/some-/path" },
1793 { is_sig, 5, "(si)" },
1794 { is_string, 4, "(si" },
1795 { is_string, 2, "*" },
1796 { is_sig, 3, "ai" },
1797 { is_string, 3, "mi" },
1798 { is_string, 2, "r" },
1799 { is_sig, 15, "(yyy{sv}ssiai)" },
1800 { is_string, 16, "(yyy{yv}ssiai))" },
1801 { is_string, 15, "(yyy{vv}ssiai)" },
1802 { is_string, 15, "(yyy{sv)ssiai}" }
1806 for (i = 0; i < G_N_ELEMENTS (test_cases); i++)
1810 flags = g_variant_serialiser_is_string (test_cases[i].data,
1814 flags |= g_variant_serialiser_is_object_path (test_cases[i].data,
1818 flags |= g_variant_serialiser_is_signature (test_cases[i].data,
1822 g_assert (flags == test_cases[i].flags);
1826 typedef struct _TreeInstance TreeInstance;
1827 struct _TreeInstance
1829 GVariantTypeInfo *info;
1831 TreeInstance **children;
1842 static GVariantType *
1843 make_random_definite_type (int depth)
1845 GString *description;
1846 GString *type_string;
1849 description = g_string_new (NULL);
1850 type_string = g_string_new (NULL);
1851 type = append_type_string (type_string, description, TRUE, depth);
1852 g_string_free (description, TRUE);
1853 g_string_free (type_string, TRUE);
1859 make_random_string (gchar *string,
1861 const GVariantType *type)
1865 /* create strings that are valid signature strings */
1866 #define good_chars "bynqiuxthdsog"
1868 for (i = 0; i < size - 1; i++)
1869 string[i] = good_chars[g_test_rand_int_range (0, strlen (good_chars))];
1872 /* in case we need an object path, prefix a '/' */
1873 if (*g_variant_type_peek_string (type) == 'o')
1879 static TreeInstance *
1880 tree_instance_new (const GVariantType *type,
1883 const GVariantType *child_type = NULL;
1884 GVariantType *mytype = NULL;
1885 TreeInstance *instance;
1886 gboolean is_tuple_type;
1889 type = mytype = make_random_definite_type (depth);
1891 instance = g_slice_new (TreeInstance);
1892 instance->info = g_variant_type_info_get (type);
1893 instance->children = NULL;
1894 instance->n_children = 0;
1895 instance->data_size = 0;
1897 is_tuple_type = FALSE;
1899 switch (*g_variant_type_peek_string (type))
1901 case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
1902 instance->n_children = g_test_rand_int_range (0, 2);
1903 child_type = g_variant_type_element (type);
1906 case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
1907 instance->n_children = g_test_rand_int_range (0, MAX_ARRAY_CHILDREN);
1908 child_type = g_variant_type_element (type);
1911 case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
1912 case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
1913 instance->n_children = g_variant_type_n_items (type);
1914 child_type = g_variant_type_first (type);
1915 is_tuple_type = TRUE;
1918 case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
1919 instance->n_children = 1;
1924 instance->data.integer = g_test_rand_int_range (0, 2);
1925 instance->data_size = 1;
1929 instance->data.integer = g_test_rand_int ();
1930 instance->data_size = 1;
1934 instance->data.integer = g_test_rand_int ();
1935 instance->data_size = 2;
1938 case 'i': case 'u': case 'h':
1939 instance->data.integer = g_test_rand_int ();
1940 instance->data_size = 4;
1943 case 'x': case 't': case 'd':
1944 instance->data.integer = g_test_rand_int ();
1945 instance->data.integer <<= 32;
1946 instance->data.integer |= (guint32) g_test_rand_int ();
1947 instance->data_size = 8;
1950 case 's': case 'o': case 'g':
1951 instance->data_size = g_test_rand_int_range (10, 20);
1952 make_random_string (instance->data.string, instance->data_size, type);
1956 if (instance->data_size == 0)
1957 /* no data -> it is a container */
1961 instance->children = g_new (TreeInstance *, instance->n_children);
1963 for (i = 0; i < instance->n_children; i++)
1965 instance->children[i] = tree_instance_new (child_type, depth - 1);
1968 child_type = g_variant_type_next (child_type);
1971 g_assert (!is_tuple_type || child_type == NULL);
1974 g_variant_type_free (mytype);
1980 tree_instance_free (TreeInstance *instance)
1984 g_variant_type_info_unref (instance->info);
1985 for (i = 0; i < instance->n_children; i++)
1986 tree_instance_free (instance->children[i]);
1987 g_free (instance->children);
1988 g_slice_free (TreeInstance, instance);
1991 static gboolean i_am_writing_byteswapped;
1994 tree_filler (GVariantSerialised *serialised,
1997 TreeInstance *instance = data;
1999 if (serialised->type_info == NULL)
2000 serialised->type_info = instance->info;
2002 if (instance->data_size == 0)
2003 /* is a container */
2005 if (serialised->size == 0)
2007 g_variant_serialiser_needed_size (instance->info, tree_filler,
2008 (gpointer *) instance->children,
2009 instance->n_children);
2011 if (serialised->data)
2012 g_variant_serialiser_serialise (*serialised, tree_filler,
2013 (gpointer *) instance->children,
2014 instance->n_children);
2019 if (serialised->size == 0)
2020 serialised->size = instance->data_size;
2022 if (serialised->data)
2024 switch (instance->data_size)
2027 *serialised->data = instance->data.integer;
2032 guint16 value = instance->data.integer;
2034 if (i_am_writing_byteswapped)
2035 value = GUINT16_SWAP_LE_BE (value);
2037 *(guint16 *) serialised->data = value;
2043 guint32 value = instance->data.integer;
2045 if (i_am_writing_byteswapped)
2046 value = GUINT32_SWAP_LE_BE (value);
2048 *(guint32 *) serialised->data = value;
2054 guint64 value = instance->data.integer;
2056 if (i_am_writing_byteswapped)
2057 value = GUINT64_SWAP_LE_BE (value);
2059 *(guint64 *) serialised->data = value;
2064 memcpy (serialised->data,
2065 instance->data.string,
2066 instance->data_size);
2074 check_tree (TreeInstance *instance,
2075 GVariantSerialised serialised)
2077 if (instance->info != serialised.type_info)
2080 if (instance->data_size == 0)
2081 /* is a container */
2085 if (g_variant_serialised_n_children (serialised) !=
2086 instance->n_children)
2089 for (i = 0; i < instance->n_children; i++)
2091 GVariantSerialised child;
2092 gpointer data = NULL;
2095 child = g_variant_serialised_get_child (serialised, i);
2096 if (child.size && child.data == NULL)
2097 child.data = data = g_malloc0 (child.size);
2098 ok = check_tree (instance->children[i], child);
2099 g_variant_type_info_unref (child.type_info);
2111 switch (instance->data_size)
2114 g_assert (serialised.size == 1);
2115 return *(guint8 *) serialised.data ==
2116 (guint8) instance->data.integer;
2119 g_assert (serialised.size == 2);
2120 return *(guint16 *) serialised.data ==
2121 (guint16) instance->data.integer;
2124 g_assert (serialised.size == 4);
2125 return *(guint32 *) serialised.data ==
2126 (guint32) instance->data.integer;
2129 g_assert (serialised.size == 8);
2130 return *(guint64 *) serialised.data ==
2131 (guint64) instance->data.integer;
2134 if (serialised.size != instance->data_size)
2137 return memcmp (serialised.data,
2138 instance->data.string,
2139 instance->data_size) == 0;
2145 serialise_tree (TreeInstance *tree,
2146 GVariantSerialised *serialised)
2148 GVariantSerialised empty = { };
2150 *serialised = empty;
2151 tree_filler (serialised, tree);
2152 serialised->data = g_malloc (serialised->size);
2153 tree_filler (serialised, tree);
2157 test_byteswap (void)
2159 GVariantSerialised one, two;
2162 tree = tree_instance_new (NULL, 3);
2163 serialise_tree (tree, &one);
2165 i_am_writing_byteswapped = TRUE;
2166 serialise_tree (tree, &two);
2167 i_am_writing_byteswapped = FALSE;
2169 g_variant_serialised_byteswap (two);
2171 g_assert_cmpint (one.size, ==, two.size);
2172 g_assert (memcmp (one.data, two.data, one.size) == 0);
2174 tree_instance_free (tree);
2180 test_byteswaps (void)
2184 for (i = 0; i < 200; i++)
2187 assert_no_type_infos ();
2191 test_fuzz (gdouble *fuzziness)
2193 GVariantSerialised serialised;
2196 /* make an instance */
2197 tree = tree_instance_new (NULL, 3);
2200 serialise_tree (tree, &serialised);
2202 g_assert (g_variant_serialised_is_normal (serialised));
2203 g_assert (check_tree (tree, serialised));
2205 if (serialised.size)
2207 gboolean fuzzed = FALSE;
2214 for (i = 0; i < serialised.size; i++)
2215 if (randomly (*fuzziness))
2217 serialised.data[i] += g_test_rand_int_range (1, 256);
2222 /* at least one byte in the serialised data has changed.
2224 * this means that at least one of the following is true:
2226 * - the serialised data now represents a different value:
2227 * check_tree() will return FALSE
2229 * - the serialised data is in non-normal form:
2230 * g_variant_serialiser_is_normal() will return FALSE
2232 * we always do both checks to increase exposure of the serialiser
2235 a = g_variant_serialised_is_normal (serialised);
2236 b = check_tree (tree, serialised);
2238 g_assert (!a || !b);
2241 tree_instance_free (tree);
2242 g_free (serialised.data);
2247 test_fuzzes (gpointer data)
2252 fuzziness = GPOINTER_TO_INT (data) / 100.;
2254 for (i = 0; i < 200; i++)
2255 test_fuzz (&fuzziness);
2257 assert_no_type_infos ();
2261 tree_instance_get_gvariant (TreeInstance *tree)
2263 const GVariantType *type;
2266 type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
2268 switch (g_variant_type_info_get_type_char (tree->info))
2270 case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
2272 const GVariantType *child_type;
2275 if (tree->n_children)
2276 child = tree_instance_get_gvariant (tree->children[0]);
2280 child_type = g_variant_type_element (type);
2282 if (child != NULL && randomly (0.5))
2285 result = g_variant_new_maybe (child_type, child);
2289 case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
2291 const GVariantType *child_type;
2292 GVariant **children;
2295 children = g_new (GVariant *, tree->n_children);
2296 for (i = 0; i < tree->n_children; i++)
2297 children[i] = tree_instance_get_gvariant (tree->children[i]);
2299 child_type = g_variant_type_element (type);
2301 if (i > 0 && randomly (0.5))
2304 result = g_variant_new_array (child_type, children, tree->n_children);
2309 case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
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 result = g_variant_new_tuple (children, tree->n_children);
2323 case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
2325 GVariant *key, *val;
2327 g_assert (tree->n_children == 2);
2329 key = tree_instance_get_gvariant (tree->children[0]);
2330 val = tree_instance_get_gvariant (tree->children[1]);
2332 result = g_variant_new_dict_entry (key, val);
2336 case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
2340 g_assert (tree->n_children == 1);
2342 value = tree_instance_get_gvariant (tree->children[0]);
2343 result = g_variant_new_variant (value);
2348 result = g_variant_new_boolean (tree->data.integer > 0);
2352 result = g_variant_new_byte (tree->data.integer);
2356 result = g_variant_new_int16 (tree->data.integer);
2360 result = g_variant_new_uint16 (tree->data.integer);
2364 result = g_variant_new_int32 (tree->data.integer);
2368 result = g_variant_new_uint32 (tree->data.integer);
2372 result = g_variant_new_int64 (tree->data.integer);
2376 result = g_variant_new_uint64 (tree->data.integer);
2380 result = g_variant_new_handle (tree->data.integer);
2384 result = g_variant_new_double (tree->data.floating);
2388 result = g_variant_new_string (tree->data.string);
2392 result = g_variant_new_object_path (tree->data.string);
2396 result = g_variant_new_signature (tree->data.string);
2400 g_assert_not_reached ();
2407 tree_instance_check_gvariant (TreeInstance *tree,
2410 const GVariantType *type;
2412 type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
2413 g_assert (g_variant_is_of_type (value, type));
2415 switch (g_variant_type_info_get_type_char (tree->info))
2417 case G_VARIANT_TYPE_INFO_CHAR_MAYBE:
2422 child = g_variant_get_maybe (value);
2424 if (child != NULL && tree->n_children == 1)
2425 equal = tree_instance_check_gvariant (tree->children[0], child);
2426 else if (child == NULL && tree->n_children == 0)
2432 g_variant_unref (child);
2438 case G_VARIANT_TYPE_INFO_CHAR_ARRAY:
2439 case G_VARIANT_TYPE_INFO_CHAR_TUPLE:
2440 case G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY:
2444 if (g_variant_n_children (value) != tree->n_children)
2447 for (i = 0; i < tree->n_children; i++)
2452 child = g_variant_get_child_value (value, i);
2453 equal = tree_instance_check_gvariant (tree->children[i], child);
2454 g_variant_unref (child);
2464 case G_VARIANT_TYPE_INFO_CHAR_VARIANT:
2466 const gchar *str1, *str2;
2470 child = g_variant_get_variant (value);
2471 str1 = g_variant_get_type_string (child);
2472 str2 = g_variant_type_info_get_type_string (tree->children[0]->info);
2474 /* can't pointer-compare str1 and str2 since one comes from the
2475 * real GVariantTypeInfo and one comes from our private copy...
2477 equal = strcmp (str1, str2) == 0 &&
2478 tree_instance_check_gvariant (tree->children[0], child);
2480 g_variant_unref (child);
2487 return g_variant_get_boolean (value) == tree->data.integer;
2490 return g_variant_get_byte (value) == (guchar) tree->data.integer;
2493 return g_variant_get_int16 (value) == (gint16) tree->data.integer;
2496 return g_variant_get_uint16 (value) == (guint16) tree->data.integer;
2499 return g_variant_get_int32 (value) == (gint32) tree->data.integer;
2502 return g_variant_get_uint32 (value) == (guint32) tree->data.integer;
2505 return g_variant_get_int64 (value) == (gint64) tree->data.integer;
2508 return g_variant_get_uint64 (value) == (guint64) tree->data.integer;
2511 return g_variant_get_handle (value) == (gint32) tree->data.integer;
2515 gdouble floating = g_variant_get_double (value);
2517 return memcmp (&floating, &tree->data.floating, sizeof floating) == 0;
2523 return strcmp (g_variant_get_string (value, NULL),
2524 tree->data.string) == 0;
2527 g_assert_not_reached ();
2532 tree_instance_build_gvariant (TreeInstance *tree,
2533 GVariantBuilder *builder)
2535 const GVariantType *type;
2537 type = (GVariantType *) g_variant_type_info_get_type_string (tree->info);
2539 if (g_variant_type_is_container (type))
2543 g_variant_builder_open (builder, type);
2545 for (i = 0; i < tree->n_children; i++)
2546 tree_instance_build_gvariant (tree->children[i], builder);
2548 g_variant_builder_close (builder);
2551 g_variant_builder_add_value (builder, tree_instance_get_gvariant (tree));
2556 tree_instance_check_iter (TreeInstance *tree,
2561 value = g_variant_iter_next_value (iter);
2563 if (g_variant_is_container (value))
2567 iter = g_variant_iter_new (value);
2568 g_variant_unref (value);
2570 if (g_variant_iter_n_children (iter) != tree->n_children)
2572 g_variant_iter_free (iter);
2576 for (i = 0; i < tree->n_children; i++)
2577 if (!tree_instance_check_iter (tree->children[i], iter))
2579 g_variant_iter_free (iter);
2583 g_assert (g_variant_iter_next_value (iter) == NULL);
2584 g_variant_iter_free (iter);
2593 equal = tree_instance_check_gvariant (tree, value);
2594 g_variant_unref (value);
2601 test_container (void)
2607 tree = tree_instance_new (NULL, 3);
2608 value = g_variant_ref_sink (tree_instance_get_gvariant (tree));
2610 s1 = g_variant_print (value, TRUE);
2611 g_assert (tree_instance_check_gvariant (tree, value));
2613 g_variant_get_data (value);
2615 s2 = g_variant_print (value, TRUE);
2616 g_assert (tree_instance_check_gvariant (tree, value));
2618 g_assert_cmpstr (s1, ==, s2);
2620 if (g_variant_is_container (value))
2622 GVariantBuilder builder;
2628 g_variant_builder_init (&builder, G_VARIANT_TYPE_VARIANT);
2629 tree_instance_build_gvariant (tree, &builder);
2630 built = g_variant_builder_end (&builder);
2631 g_variant_ref_sink (built);
2632 g_variant_get_data (built);
2633 val = g_variant_get_variant (built);
2635 s3 = g_variant_print (val, TRUE);
2636 g_assert_cmpstr (s1, ==, s3);
2638 g_variant_iter_init (&iter, built);
2639 g_assert (tree_instance_check_iter (tree, &iter));
2640 g_assert (g_variant_iter_next_value (&iter) == NULL);
2642 g_variant_unref (built);
2643 g_variant_unref (val);
2647 tree_instance_free (tree);
2648 g_variant_unref (value);
2654 test_containers (void)
2658 for (i = 0; i < 100; i++)
2665 main (int argc, char **argv)
2669 g_test_init (&argc, &argv, NULL);
2671 g_test_add_func ("/gvariant/type", test_gvarianttype);
2672 g_test_add_func ("/gvariant/typeinfo", test_gvarianttypeinfo);
2673 g_test_add_func ("/gvariant/serialiser/maybe", test_maybes);
2674 g_test_add_func ("/gvariant/serialiser/array", test_arrays);
2675 g_test_add_func ("/gvariant/serialiser/tuple", test_tuples);
2676 g_test_add_func ("/gvariant/serialiser/variant", test_variants);
2677 g_test_add_func ("/gvariant/serialiser/strings", test_strings);
2678 g_test_add_func ("/gvariant/serialiser/byteswap", test_byteswaps);
2680 for (i = 1; i <= 20; i += 4)
2684 testname = g_strdup_printf ("/gvariant/serialiser/fuzz/%d%%", i);
2685 g_test_add_data_func (testname, GINT_TO_POINTER (i),
2686 (gpointer) test_fuzzes);
2690 g_test_add_func ("/gvariant/containers", test_containers);
2692 return g_test_run ();