[glib/GVariantType] GVariantType test: add subtype checking
- From: Ryan Lortie <ryanl src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [glib/GVariantType] GVariantType test: add subtype checking
- Date: Sat, 23 Jan 2010 01:12:50 +0000 (UTC)
commit 9dd33c1c3f03456871b7efa9758eeefe2af90364
Author: Ryan Lortie <desrt desrt ca>
Date: Fri Jan 22 20:10:18 2010 -0500
GVariantType test: add subtype checking
glib/tests/gvarianttype.c | 201 +++++++++++++++++++++++++++++++++++++--------
1 files changed, 167 insertions(+), 34 deletions(-)
---
diff --git a/glib/tests/gvarianttype.c b/glib/tests/gvarianttype.c
index 3a49f81..c354e74 100644
--- a/glib/tests/gvarianttype.c
+++ b/glib/tests/gvarianttype.c
@@ -26,6 +26,9 @@ randomly (gdouble prob)
return g_test_rand_double_range (0, 1) < prob;
}
+/* corecursion */
+static GVariantType *append_tuple_type_string (GString *, GString *, gint);
+
/* append a random GVariantType to a GString
* append a description of the type to another GString
* return what the type is
@@ -110,39 +113,7 @@ append_type_string (GString *string,
break;
case 2:
- {
- GVariantType *other_result;
- GVariantType **types;
- gint size;
- gint i;
-
- g_string_append_c (string, '(');
- g_string_append (description, "t of [");
-
- size = g_test_rand_int_range (0, 20);
- types = g_new (GVariantType *, size + 1);
-
- for (i = 0; i < size; i++)
- {
- types[i] = append_type_string (string, description, depth);
-
- if (i < size - 1)
- g_string_append (description, ", ");
- }
-
- types[i] = NULL;
-
- g_string_append_c (description, ']');
- g_string_append_c (string, ')');
-
- result = g_variant_type_new_tuple ((gpointer) types, size);
- other_result = g_variant_type_new_tuple ((gpointer) types, -1);
- g_assert (g_variant_type_equal (result, other_result));
- g_variant_type_free (other_result);
- for (i = 0; i < size; i++)
- g_variant_type_free (types[i]);
- g_free (types);
- }
+ result = append_tuple_type_string (string, description, depth);
g_assert (g_variant_type_is_tuple (result));
break;
@@ -195,6 +166,46 @@ append_type_string (GString *string,
}
}
+static GVariantType *
+append_tuple_type_string (GString *string,
+ GString *description,
+ gint depth)
+{
+ GVariantType *result, *other_result;
+ GVariantType **types;
+ gint size;
+ gint i;
+
+ g_string_append_c (string, '(');
+ g_string_append (description, "t of [");
+
+ size = g_test_rand_int_range (0, 20);
+ types = g_new (GVariantType *, size + 1);
+
+ for (i = 0; i < size; i++)
+ {
+ types[i] = append_type_string (string, description, depth);
+
+ if (i < size - 1)
+ g_string_append (description, ", ");
+ }
+
+ types[i] = NULL;
+
+ g_string_append_c (description, ']');
+ g_string_append_c (string, ')');
+
+ result = g_variant_type_new_tuple ((gpointer) types, size);
+ other_result = g_variant_type_new_tuple ((gpointer) types, -1);
+ g_assert (g_variant_type_equal (result, other_result));
+ g_variant_type_free (other_result);
+ for (i = 0; i < size; i++)
+ g_variant_type_free (types[i]);
+ g_free (types);
+
+ return result;
+}
+
/* given a valid type string, make it invalid */
static gchar *
invalid_mutation (const gchar *type_string)
@@ -447,12 +458,118 @@ describe_type (const GVariantType *type)
return result;
}
+/* given a type string, replace one of the indefinite type characters in
+ * it with a matching type (possibly the same type).
+ */
+static gchar *
+generate_subtype (const gchar *type_string)
+{
+ GVariantType *replacement;
+ GString *result, *junk;
+ gint length, n = 0, l;
+
+ result = g_string_new (NULL);
+ junk = g_string_new (NULL);
+
+ /* count the number of indefinite type characters */
+ for (length = 0; type_string[length]; length++)
+ n += type_string[length] == 'r' ||
+ type_string[length] == '?' ||
+ type_string[length] == '*';
+ /* length now is strlen (type_string) */
+
+ /* pick one at random to replace */
+ n = g_test_rand_int_range (0, n) + 1;
+
+ /* find it */
+ l = -1;
+ while (n--) l += strcspn (type_string + l + 1, "r?*") + 1;
+ g_assert (type_string[l] == 'r' ||
+ type_string[l] == '?' ||
+ type_string[l] == '*');
+
+ /* store up to that point in a GString */
+ g_string_append_len (result, type_string, l);
+
+ /* then store the replacement in the GString */
+ if (type_string[l] == 'r')
+ replacement = append_tuple_type_string (result, junk, 3);
+
+ else if (type_string[l] == '?')
+ replacement = append_type_string (result, junk, 0);
+
+ else if (type_string[l] == '*')
+ replacement = append_type_string (result, junk, 3);
+
+ else
+ g_assert_not_reached ();
+
+ /* ensure the replacement has the proper type */
+ g_assert (g_variant_type_is_subtype_of (replacement,
+ (gpointer) &type_string[l]));
+
+ /* store the rest from the original type string */
+ g_string_append (result, type_string + l + 1);
+
+ g_variant_type_free (replacement);
+ g_string_free (junk, TRUE);
+
+ return g_string_free (result, FALSE);
+}
+
+struct typestack
+{
+ const GVariantType *type;
+ struct typestack *parent;
+};
+
+/* given an indefinite type string, replace one of the indefinite
+ * characters in it with a matching type and ensure that the result is a
+ * subtype of the original. repeat.
+ */
+static void
+subtype_check (const gchar *type_string,
+ struct typestack *parent_ts)
+{
+ struct typestack ts, *node;
+ gchar *subtype;
+ gint depth = 0;
+
+ subtype = generate_subtype (type_string);
+
+ ts.type = G_VARIANT_TYPE (subtype);
+ ts.parent = parent_ts;
+
+ for (node = &ts; node; node = node->parent)
+ {
+ /* this type should be a subtype of each parent type */
+ g_assert (g_variant_type_is_subtype_of (ts.type, node->type));
+
+ /* but it should not be a supertype unless it is equal */
+ g_assert (!g_variant_type_is_subtype_of (node->type, ts.type) ||
+ g_variant_type_equal (ts.type, node->type));
+
+ depth++;
+ }
+
+ if (!g_variant_type_is_definite (ts.type) && depth < 5)
+ {
+ /* the type is still indefinite and we haven't repeated too many
+ * times. go once more.
+ */
+
+ subtype_check (subtype, &ts);
+ }
+
+ g_free (subtype);
+}
+
static void
test_gvarianttype (void)
{
gint i;
- for (i = 0; i < 10000; i++)
+ for (i = 0; i < 2000; i++)
{
GString *type_string, *description;
GVariantType *type, *other_type;
@@ -477,6 +594,22 @@ test_gvarianttype (void)
g_assert (g_variant_type_is_subtype_of (ctype, type));
g_assert (g_variant_type_is_subtype_of (type, ctype));
+ /* check if the type is indefinite */
+ if (!g_variant_type_is_definite (type))
+ {
+ struct typestack ts = { type, NULL };
+
+ /* if it is indefinite, then replace one of the indefinite
+ * characters with a matching type and ensure that the result
+ * is a subtype of the original type. repeat.
+ */
+ subtype_check (type_string->str, &ts);
+ }
+ else
+ /* ensure that no indefinite characters appear */
+ g_assert (strcspn (type_string->str, "r?*") == type_string->len);
+
+
/* describe the type.
*
* exercises the type iterator interface
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]