[glib/GVariantType] Add test case for GVariantType



commit b564db8c724358e7e5723b1017ceb8dfaee65c4a
Author: Ryan Lortie <desrt desrt ca>
Date:   Fri Jan 22 19:20:57 2010 -0500

    Add test case for GVariantType

 glib/tests/.gitignore     |    1 +
 glib/tests/Makefile.am    |    3 +
 glib/tests/gvarianttype.c |  488 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 492 insertions(+), 0 deletions(-)
---
diff --git a/glib/tests/.gitignore b/glib/tests/.gitignore
index 76c25a8..7b02941 100644
--- a/glib/tests/.gitignore
+++ b/glib/tests/.gitignore
@@ -1,5 +1,6 @@
 array-test
 fileutils
+gvarianttype
 hostutils
 keyfile
 markup-subparser
diff --git a/glib/tests/Makefile.am b/glib/tests/Makefile.am
index 673d338..3d3b8d4 100644
--- a/glib/tests/Makefile.am
+++ b/glib/tests/Makefile.am
@@ -47,6 +47,9 @@ array_test_LDADD    = $(progs_ldadd)
 TEST_PROGS         += hostutils
 hostutils_LDADD     = $(progs_ldadd)
 
+TEST_PROGS         += gvarianttype
+gvarianttype_LDADD  = $(progs_ldadd)
+
 if OS_UNIX
 
 # some testing of gtester funcitonality
diff --git a/glib/tests/gvarianttype.c b/glib/tests/gvarianttype.c
new file mode 100644
index 0000000..dc71837
--- /dev/null
+++ b/glib/tests/gvarianttype.c
@@ -0,0 +1,488 @@
+/*
+ * Copyright © 2010 Codethink Limited
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the licence, or (at your option) any later version.
+ *
+ * See the included COPYING file for more information.
+ *
+ * Author: Ryan Lortie <desrt desrt ca>
+ */
+
+#include <string.h>
+#include <glib.h>
+
+#define BASIC "bynqiuxthdsog?"
+#define N_BASIC (G_N_ELEMENTS (BASIC) - 1)
+
+#define INVALIDS "cefjklpwz&@^$"
+#define N_INVALIDS (G_N_ELEMENTS (INVALIDS) - 1)
+
+static gboolean
+randomly (gdouble prob)
+{
+  return g_test_rand_double_range (0, 1) < prob;
+}
+
+static GVariantType *
+append_type_string (GString *string,
+                    GString *description,
+                    gint     depth)
+{
+  if (!depth-- || randomly (0.3))
+    {
+      gchar b = BASIC[g_test_rand_int_range (0, N_BASIC)];
+      g_string_append_c (string, b);
+      g_string_append_c (description, b);
+
+      switch (b)
+        {
+        case 'b':
+          return g_variant_type_copy (G_VARIANT_TYPE_BOOLEAN);
+        case 'y':
+          return g_variant_type_copy (G_VARIANT_TYPE_BYTE);
+        case 'n':
+          return g_variant_type_copy (G_VARIANT_TYPE_INT16);
+        case 'q':
+          return g_variant_type_copy (G_VARIANT_TYPE_UINT16);
+        case 'i':
+          return g_variant_type_copy (G_VARIANT_TYPE_INT32);
+        case 'u':
+          return g_variant_type_copy (G_VARIANT_TYPE_UINT32);
+        case 'x':
+          return g_variant_type_copy (G_VARIANT_TYPE_INT64);
+        case 't':
+          return g_variant_type_copy (G_VARIANT_TYPE_UINT64);
+        case 'h':
+          return g_variant_type_copy (G_VARIANT_TYPE_HANDLE);
+        case 'd':
+          return g_variant_type_copy (G_VARIANT_TYPE_DOUBLE);
+        case 's':
+          return g_variant_type_copy (G_VARIANT_TYPE_STRING);
+        case 'o':
+          return g_variant_type_copy (G_VARIANT_TYPE_OBJECT_PATH);
+        case 'g':
+          return g_variant_type_copy (G_VARIANT_TYPE_SIGNATURE);
+        case '?':
+          return g_variant_type_copy (G_VARIANT_TYPE_BASIC);
+        default:
+          g_assert_not_reached ();
+        }
+    }
+  else
+    {
+      GVariantType *result;
+
+      switch (g_test_rand_int_range (0, 7))
+        {
+        case 0:
+          {
+            GVariantType *element;
+
+            g_string_append_c (string, 'a');
+            g_string_append (description, "a of ");
+            element = append_type_string (string, description, depth);
+            result = g_variant_type_new_array (element);
+            g_variant_type_free (element);
+          }
+
+          g_assert (g_variant_type_is_array (result));
+          break;
+
+        case 1:
+          {
+            GVariantType *element;
+
+            g_string_append_c (string, 'm');
+            g_string_append (description, "m of ");
+            element = append_type_string (string, description, depth);
+            result = g_variant_type_new_maybe (element);
+            g_variant_type_free (element);
+          }
+
+          g_assert (g_variant_type_is_maybe (result));
+          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);
+          }
+
+          g_assert (g_variant_type_is_tuple (result));
+          break;
+
+        case 3:
+          {
+            GVariantType *key, *value;
+
+            g_string_append_c (string, '{');
+            g_string_append (description, "e of [");
+            key = append_type_string (string, description, 0);
+            g_string_append (description, ", ");
+            value = append_type_string (string, description, depth);
+            g_string_append_c (description, ']');
+            g_string_append_c (string, '}');
+            result = g_variant_type_new_dict_entry (key, value);
+            g_variant_type_free (key);
+            g_variant_type_free (value);
+          }
+
+          g_assert (g_variant_type_is_dict_entry (result));
+          break;
+
+        case 4:
+          g_string_append_c (string, 'v');
+          g_string_append_c (description, 'V');
+          result = g_variant_type_copy (G_VARIANT_TYPE_VARIANT);
+          g_assert (g_variant_type_equal (result, G_VARIANT_TYPE_VARIANT));
+          break;
+
+        case 5:
+          g_string_append_c (string, '*');
+          g_string_append_c (description, 'S');
+          result = g_variant_type_copy (G_VARIANT_TYPE_ANY);
+          g_assert (g_variant_type_equal (result, G_VARIANT_TYPE_ANY));
+          break;
+
+        case 6:
+          g_string_append_c (string, 'r');
+          g_string_append_c (description, 'R');
+          result = g_variant_type_copy (G_VARIANT_TYPE_TUPLE);
+          g_assert (g_variant_type_is_tuple (result));
+          break;
+
+        default:
+          g_assert_not_reached ();
+        }
+
+      return result;
+    }
+}
+
+/* given a valid type string, make it invalid */
+static gchar *
+invalid_mutation (const gchar *type_string)
+{
+  gboolean have_parens, have_braces;
+
+  /* it's valid, so '(' implies ')' and same for '{' and '}' */
+  have_parens = strchr (type_string, '(') != NULL;
+  have_braces = strchr (type_string, '{') != NULL;
+
+  if (have_parens && have_braces && randomly (0.3))
+    {
+      /* swap a paren and a brace */
+      gchar *pp, *bp;
+      gint np, nb;
+      gchar p, b;
+      gchar *new;
+
+      new = g_strdup (type_string);
+
+      if (randomly (0.5))
+        p = '(', b = '{';
+      else
+        p = ')', b = '}';
+
+      np = nb = 0;
+      pp = bp = new - 1;
+
+      /* count number of parens/braces */
+      while ((pp = strchr (pp + 1, p))) np++;
+      while ((bp = strchr (bp + 1, b))) nb++;
+
+      /* randomly pick one of each */
+      np = g_test_rand_int_range (0, np) + 1;
+      nb = g_test_rand_int_range (0, nb) + 1;
+
+      /* find it */
+      pp = bp = new - 1;
+      while (np--) pp = strchr (pp + 1, p);
+      while (nb--) bp = strchr (bp + 1, b);
+
+      /* swap */
+      g_assert (*bp == b && *pp == p);
+      *bp = p;
+      *pp = b;
+
+      return new;
+    }
+
+  if ((have_parens || have_braces) && randomly (0.3))
+    {
+      /* drop a paren/brace */
+      gchar *new;
+      gchar *pp;
+      gint np;
+      gchar p;
+
+      if (have_parens)
+        if (randomly (0.5)) p = '('; else p = ')';
+      else
+        if (randomly (0.5)) p = '{'; else p = '}';
+
+      new = g_strdup (type_string);
+
+      np = 0;
+      pp = new - 1;
+      while ((pp = strchr (pp + 1, p))) np++;
+      np = g_test_rand_int_range (0, np) + 1;
+      pp = new - 1;
+      while (np--) pp = strchr (pp + 1, p);
+      g_assert (*pp == p);
+
+      while (*pp)
+        {
+          *pp = *(pp + 1);
+          pp++;
+        }
+
+      return new;
+    }
+
+  /* else, perform a random mutation at a random point */
+  {
+    gint length, n;
+    gchar *new;
+    gchar p;
+
+    if (randomly (0.3))
+      {
+        /* insert a paren/brace */
+        if (randomly (0.5))
+          if (randomly (0.5)) p = '('; else p = ')';
+        else
+          if (randomly (0.5)) p = '{'; else p = '}';
+      }
+    else if (randomly (0.5))
+      {
+        /* insert junk */
+        p = INVALIDS[g_test_rand_int_range (0, N_INVALIDS)];
+      }
+    else
+      {
+        /* truncate */
+        p = '\0';
+      }
+
+
+    length = strlen (type_string);
+    new = g_malloc (length + 2);
+    n = g_test_rand_int_range (0, length);
+    memcpy (new, type_string, n);
+    new[n] = p;
+    memcpy (new + n + 1, type_string + n, length - n);
+    new[length + 1] = '\0';
+
+    return new;
+  }
+}
+
+static gchar *
+describe_type (const GVariantType *type)
+{
+  gchar *result;
+
+  if (g_variant_type_is_container (type))
+    {
+      g_assert (!g_variant_type_is_basic (type));
+
+      if (g_variant_type_is_array (type))
+        {
+          gchar *subtype = describe_type (g_variant_type_element (type));
+          result = g_strdup_printf ("a of %s", subtype);
+          g_free (subtype);
+        }
+      else if (g_variant_type_is_maybe (type))
+        {
+          gchar *subtype = describe_type (g_variant_type_element (type));
+          result = g_strdup_printf ("m of %s", subtype);
+          g_free (subtype);
+        }
+      else if (g_variant_type_is_tuple (type))
+        {
+          if (!g_variant_type_equal (type, G_VARIANT_TYPE_TUPLE))
+            {
+              const GVariantType *sub;
+              GString *string;
+              gint length;
+              gint i;
+
+              string = g_string_new ("t of [");
+
+              length = g_variant_type_n_items (type);
+              sub = g_variant_type_first (type);
+              for (i = 0; i < length; i++)
+                {
+                  gchar *subtype = describe_type (sub);
+                  g_string_append (string, subtype);
+                  g_free (subtype);
+
+                  if ((sub = g_variant_type_next (sub)))
+                    g_string_append (string, ", ");
+                }
+              g_assert (sub == NULL);
+              g_string_append_c (string, ']');
+
+              result = g_string_free (string, FALSE);
+            }
+          else
+            result = g_strdup ("R");
+        }
+      else if (g_variant_type_is_dict_entry (type))
+        {
+          gchar *key, *value, *key2, *value2;
+
+          key = describe_type (g_variant_type_key (type));
+          value = describe_type (g_variant_type_value (type));
+          key2 = describe_type (g_variant_type_first (type));
+          value2 = describe_type (
+            g_variant_type_next (g_variant_type_first (type)));
+          g_assert (g_variant_type_next (g_variant_type_next (
+            g_variant_type_first (type))) == NULL);
+          g_assert_cmpstr (key, ==, key2);
+          g_assert_cmpstr (value, ==, value2);
+          result = g_strjoin ("", "e of [", key, ", ", value, "]", NULL);
+          g_free (key2);
+          g_free (value2);
+          g_free (key);
+          g_free (value);
+        }
+      else if (g_variant_type_equal (type, G_VARIANT_TYPE_VARIANT))
+        {
+          result = g_strdup ("V");
+        }
+      else
+        g_assert_not_reached ();
+    }
+  else
+    {
+      if (g_variant_type_is_definite (type))
+        {
+          g_assert (g_variant_type_is_basic (type));
+
+          if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN))
+            result = g_strdup ("b");
+          else if (g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
+            result = g_strdup ("y");
+          else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT16))
+            result = g_strdup ("n");
+          else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT16))
+            result = g_strdup ("q");
+          else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32))
+            result = g_strdup ("i");
+          else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT32))
+            result = g_strdup ("u");
+          else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT64))
+            result = g_strdup ("x");
+          else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT64))
+            result = g_strdup ("t");
+          else if (g_variant_type_equal (type, G_VARIANT_TYPE_HANDLE))
+            result = g_strdup ("h");
+          else if (g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
+            result = g_strdup ("d");
+          else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING))
+            result = g_strdup ("s");
+          else if (g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH))
+            result = g_strdup ("o");
+          else if (g_variant_type_equal (type, G_VARIANT_TYPE_SIGNATURE))
+            result = g_strdup ("g");
+          else
+            g_assert_not_reached ();
+        }
+      else
+        {
+          if (g_variant_type_equal (type, G_VARIANT_TYPE_ANY))
+            {
+              result = g_strdup ("S");
+            }
+          else if (g_variant_type_equal (type, G_VARIANT_TYPE_BASIC))
+            {
+              result = g_strdup ("?");
+            }
+          else
+            g_assert_not_reached ();
+        }
+    }
+
+  return result;
+}
+
+static void
+test_gvarianttype (void)
+{
+  gint i;
+
+  for (i = 0; i < 10000; i++)
+    {
+      GString *type_string, *description;
+      const GVariantType *ctype;
+      GVariantType *type;
+      gchar *invalid;
+      gchar *desc;
+
+      type_string = g_string_new (NULL);
+      description = g_string_new (NULL);
+
+      type = append_type_string (type_string, description, 6);
+      desc = describe_type (type);
+      g_assert_cmpstr (desc, ==, description->str);
+
+      invalid = invalid_mutation (type_string->str);
+      g_assert (g_variant_type_string_is_valid (type_string->str));
+      g_assert (!g_variant_type_string_is_valid (invalid));
+
+      ctype = G_VARIANT_TYPE (type_string->str);
+      g_assert (g_variant_type_equal (ctype, type));
+      g_assert (g_variant_type_is_subtype_of (ctype, type));
+      g_assert (g_variant_type_is_subtype_of (type, ctype));
+
+      g_string_free (description, TRUE);
+      g_string_free (type_string, TRUE);
+      g_variant_type_free (type);
+      g_free (invalid);
+      g_free (desc);
+    }
+}
+
+int
+main (int argc, char **argv)
+{
+  g_test_init (&argc, &argv, NULL);
+
+  g_test_add_func ("/gvariant/type", test_gvarianttype);
+
+  return g_test_run ();
+}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]