Imported Upstream version 2.53.3
[platform/upstream/glib.git] / glib / tests / gvariant.c
index 0558361..fdaed1a 100644 (file)
@@ -4,7 +4,7 @@
  * 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.
+ * version 2.1 of the License, or (at your option) any later version.
  *
  * See the included COPYING file for more information.
  *
@@ -1520,7 +1520,9 @@ test_array (void)
         g_variant_serialiser_serialise (serialised, random_instance_filler,
                                         (gpointer *) instances, n_children);
 
-        g_assert (memcmp (serialised.data, data, serialised.size) == 0);
+        if (serialised.size)
+          g_assert (memcmp (serialised.data, data, serialised.size) == 0);
+
         g_assert (g_variant_serialised_n_children (serialised) == n_children);
 
         for (i = 0; i < n_children; i++)
@@ -1681,7 +1683,9 @@ test_tuple (void)
         g_variant_serialiser_serialise (serialised, random_instance_filler,
                                         (gpointer *) instances, n_children);
 
-        g_assert (memcmp (serialised.data, data, serialised.size) == 0);
+        if (serialised.size)
+          g_assert (memcmp (serialised.data, data, serialised.size) == 0);
+
         g_assert (g_variant_serialised_n_children (serialised) == n_children);
 
         for (i = 0; i < n_children; i++)
@@ -1774,7 +1778,9 @@ test_variant (void)
         g_variant_serialiser_serialise (serialised, random_instance_filler,
                                         (gpointer *) &instance, 1);
 
-        g_assert (memcmp (serialised.data, data, serialised.size) == 0);
+        if (serialised.size)
+          g_assert (memcmp (serialised.data, data, serialised.size) == 0);
+
         g_assert (g_variant_serialised_n_children (serialised) == 1);
 
         child = g_variant_serialised_get_child (serialised, 0);
@@ -1879,7 +1885,7 @@ struct _TreeInstance
   union {
     guint64 integer;
     gdouble floating;
-    gchar string[32];
+    gchar string[200];
   } data;
   gsize data_size;
 };
@@ -1998,7 +2004,7 @@ tree_instance_new (const GVariantType *type,
       break;
 
     case 's': case 'o': case 'g':
-      instance->data_size = g_test_rand_int_range (10, 20);
+      instance->data_size = g_test_rand_int_range (10, 200);
       make_random_string (instance->data.string, instance->data_size, type);
       break;
     }
@@ -2195,7 +2201,7 @@ static void
 serialise_tree (TreeInstance       *tree,
                 GVariantSerialised *serialised)
 {
-  GVariantSerialised empty = {  };
+  GVariantSerialised empty = {0, };
 
   *serialised = empty;
   tree_filler (serialised, tree);
@@ -2218,8 +2224,7 @@ test_byteswap (void)
 
   g_variant_serialised_byteswap (two);
 
-  g_assert_cmpint (one.size, ==, two.size);
-  g_assert (memcmp (one.data, two.data, one.size) == 0);
+  g_assert_cmpmem (one.data, one.size, two.data, two.size);
 
   tree_instance_free (tree);
   g_free (one.data);
@@ -2717,6 +2722,26 @@ test_container (void)
 }
 
 static void
+test_string (void)
+{
+  /* Test some different methods of creating strings */
+  GVariant *v;
+
+  v = g_variant_new_string ("foo");
+  g_assert_cmpstr (g_variant_get_string (v, NULL), ==, "foo");
+  g_variant_unref (v);
+
+
+  v = g_variant_new_take_string (g_strdup ("foo"));
+  g_assert_cmpstr (g_variant_get_string (v, NULL), ==, "foo");
+  g_variant_unref (v);
+
+  v = g_variant_new_printf ("%s %d", "foo", 123);
+  g_assert_cmpstr (g_variant_get_string (v, NULL), ==, "foo 123");
+  g_variant_unref (v);
+}
+
+static void
 test_utf8 (void)
 {
   const gchar invalid[] = "hello\xffworld";
@@ -2844,7 +2869,7 @@ test_invalid_varargs (void)
 
   value = g_variant_new ("y", 'a');
   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
-                         "*type of `q' but * has a type of `y'*");
+                         "*type of 'q' but * has a type of 'y'*");
   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
                          "*valid_format_string*");
   g_variant_get (value, "q");
@@ -3721,11 +3746,31 @@ test_parses (void)
     g_free (printed);
   }
 
+  /* escapes */
+  {
+    const gchar orig[] = " \342\200\254 \360\220\210\240 \a \b \f \n \r \t \v ";
+    GVariant *value;
+    gchar *printed;
+
+    value = g_variant_new_string (orig);
+    printed = g_variant_print (value, FALSE);
+    g_variant_unref (value);
+
+    g_assert_cmpstr (printed, ==, "' \\u202c \\U00010220 \\a \\b \\f \\n \\r \\t \\v '");
+    value = g_variant_parse (NULL, printed, NULL, NULL, NULL);
+    g_assert_cmpstr (g_variant_get_string (value, NULL), ==, orig);
+    g_variant_unref (value);
+    g_free (printed);
+  }
+
+#ifndef _MSC_VER
+  /* inf/nan strings are C99 features which Visual C++ does not support */
   /* inf/nan mini test */
   {
     const gchar *tests[] = { "inf", "-inf", "nan" };
     GVariant *value;
     gchar *printed;
+    gchar *printed_down;
     gint i;
 
     for (i = 0; i < G_N_ELEMENTS (tests); i++)
@@ -3733,11 +3778,15 @@ test_parses (void)
         GError *error = NULL;
         value = g_variant_parse (NULL, tests[i], NULL, NULL, &error);
         printed = g_variant_print (value, FALSE);
-        g_assert (g_str_has_prefix (printed, tests[i]));
+        /* Canonicalize to lowercase; https://bugzilla.gnome.org/show_bug.cgi?id=704585 */
+        printed_down = g_ascii_strdown (printed, -1);
+        g_assert (g_str_has_prefix (printed_down, tests[i]));
         g_free (printed);
+        g_free (printed_down);
         g_variant_unref (value);
       }
   }
+#endif
 
   g_variant_type_info_assert_no_infos ();
 }
@@ -3749,7 +3798,7 @@ test_parse_failures (void)
     "[1, 2,",                   "6:",              "expected value",
     "",                         "0:",              "expected value",
     "(1, 2,",                   "6:",              "expected value",
-    "<1",                       "2:",              "expected `>'",
+    "<1",                       "2:",              "expected '>'",
     "[]",                       "0-2:",            "unable to infer",
     "(,",                       "1:",              "expected value",
     "[4,'']",                   "1-2,3-5:",        "common type",
@@ -3763,7 +3812,7 @@ test_parse_failures (void)
     "just [4, '']",             "6-7,9-11:",       "common type",
     "[[4,'']]",                 "2-3,4-6:",        "common type",
     "([4,''],)",                "2-3,4-6:",        "common type",
-    "(4)",                      "2:",              "`,'",
+    "(4)",                      "2:",              "','",
     "{}",                       "0-2:",            "unable to infer",
     "{[1,2],[3,4]}",            "0-13:",           "basic types",
     "{[1,2]:[3,4]}",            "0-13:",           "basic types",
@@ -3783,12 +3832,12 @@ test_parse_failures (void)
     "@i ()",                    "3-5:",            "can not parse as",
     "@ai (4,)",                 "4-8:",            "can not parse as",
     "@(i) []",                  "5-7:",            "can not parse as",
-    "(5 5)",                    "3:",              "expected `,'",
-    "[5 5]",                    "3:",              "expected `,' or `]'",
-    "(5, 5 5)",                 "6:",              "expected `,' or `)'",
-    "[5, 5 5]",                 "6:",              "expected `,' or `]'",
+    "(5 5)",                    "3:",              "expected ','",
+    "[5 5]",                    "3:",              "expected ',' or ']'",
+    "(5, 5 5)",                 "6:",              "expected ',' or ')'",
+    "[5, 5 5]",                 "6:",              "expected ',' or ']'",
     "<@i []>",                  "4-6:",            "can not parse as",
-    "<[5 5]>",                  "4:",              "expected `,' or `]'",
+    "<[5 5]>",                  "4:",              "expected ',' or ']'",
     "{[4,''],5}",               "2-3,4-6:",        "common type",
     "{5,[4,'']}",               "4-5,6-8:",        "common type",
     "@i {1,2}",                 "3-8:",            "can not parse as",
@@ -3797,20 +3846,20 @@ test_parse_failures (void)
     "@ai {}",                   "4-6:",            "can not parse as",
     "{@i '': 5}",               "4-6:",            "can not parse as",
     "{5: @i ''}",               "7-9:",            "can not parse as",
-    "{<4,5}",                   "3:",              "expected `>'",
-    "{4,<5}",                   "5:",              "expected `>'",
-    "{4,5,6}",                  "4:",              "expected `}'",
-    "{5 5}",                    "3:",              "expected `:' or `,'",
-    "{4: 5: 6}",                "5:",              "expected `,' or `}'",
-    "{4:5,<6:7}",               "7:",              "expected `>'",
-    "{4:5,6:<7}",               "9:",              "expected `>'",
-    "{4:5,6 7}",                "7:",              "expected `:'",
+    "{<4,5}",                   "3:",              "expected '>'",
+    "{4,<5}",                   "5:",              "expected '>'",
+    "{4,5,6}",                  "4:",              "expected '}'",
+    "{5 5}",                    "3:",              "expected ':' or ','",
+    "{4: 5: 6}",                "5:",              "expected ',' or '}'",
+    "{4:5,<6:7}",               "7:",              "expected '>'",
+    "{4:5,6:<7}",               "9:",              "expected '>'",
+    "{4:5,6 7}",                "7:",              "expected ':'",
     "@o 'foo'",                 "3-8:",            "object path",
     "@g 'zzz'",                 "3-8:",            "signature",
     "@i true",                  "3-7:",            "can not parse as",
     "@z 4",                     "0-2:",            "invalid type",
     "@a* []",                   "0-3:",            "definite",
-    "@ai [3 3]",                "7:",              "expected `,' or `]'",
+    "@ai [3 3]",                "7:",              "expected ',' or ']'",
     "18446744073709551616",     "0-20:",           "too big for any type",
     "-18446744073709551616",    "0-21:",           "too big for any type",
     "byte 256",                 "5-8:",            "out of range for type",
@@ -3853,11 +3902,11 @@ test_parse_failures (void)
       g_assert (value == NULL);
 
       if (!strstr (error->message, test[i+2]))
-        g_error ("test %d: Can't find `%s' in `%s'", i / 3,
+        g_error ("test %d: Can't find '%s' in '%s'", i / 3,
                  test[i+2], error->message);
 
       if (!g_str_has_prefix (error->message, test[i+1]))
-        g_error ("test %d: Expected location `%s' in `%s'", i / 3,
+        g_error ("test %d: Expected location '%s' in '%s'", i / 3,
                  test[i+1], error->message);
 
       g_error_free (error);
@@ -3910,7 +3959,7 @@ test_parse_positional (void)
                       "*can not parse as*");
 
       do_failed_test ("/gvariant/parse/subprocess/bad-args",
-                      "*expected GVariant of type `i'*");
+                      "*expected GVariant of type 'i'*");
     }
 }
 
@@ -4081,23 +4130,84 @@ test_lookup (void)
   g_variant_unref (dict);
 }
 
+static GVariant *
+untrusted (GVariant *a)
+{
+  GVariant *b;
+  const GVariantType *type;
+  GBytes *bytes;
+
+  type = g_variant_get_type (a);
+  bytes = g_variant_get_data_as_bytes (a);
+  b = g_variant_new_from_bytes (type, bytes, FALSE);
+  g_bytes_unref (bytes);
+  g_variant_unref (a);
+
+  return b;
+}
+
 static void
 test_compare (void)
 {
   GVariant *a;
   GVariant *b;
 
-  a = g_variant_new_byte (5);
+  a = untrusted (g_variant_new_byte (5));
   b = g_variant_new_byte (6);
   g_assert (g_variant_compare (a, b) < 0);
   g_variant_unref (a);
   g_variant_unref (b);
-  a = g_variant_new_string ("abc");
+  a = untrusted (g_variant_new_int16 (G_MININT16));
+  b = g_variant_new_int16 (G_MAXINT16);
+  g_assert (g_variant_compare (a, b) < 0);
+  g_variant_unref (a);
+  g_variant_unref (b);
+  a = untrusted (g_variant_new_uint16 (0));
+  b = g_variant_new_uint16 (G_MAXUINT16);
+  g_assert (g_variant_compare (a, b) < 0);
+  g_variant_unref (a);
+  g_variant_unref (b);
+  a = untrusted (g_variant_new_int32 (G_MININT32));
+  b = g_variant_new_int32 (G_MAXINT32);
+  g_assert (g_variant_compare (a, b) < 0);
+  g_variant_unref (a);
+  g_variant_unref (b);
+  a = untrusted (g_variant_new_uint32 (0));
+  b = g_variant_new_uint32 (G_MAXUINT32);
+  g_assert (g_variant_compare (a, b) < 0);
+  g_variant_unref (a);
+  g_variant_unref (b);
+  a = untrusted (g_variant_new_int64 (G_MININT64));
+  b = g_variant_new_int64 (G_MAXINT64);
+  g_assert (g_variant_compare (a, b) < 0);
+  g_variant_unref (a);
+  g_variant_unref (b);
+  a = untrusted (g_variant_new_uint64 (0));
+  b = g_variant_new_uint64 (G_MAXUINT64);
+  g_assert (g_variant_compare (a, b) < 0);
+  g_variant_unref (a);
+  g_variant_unref (b);
+  a = untrusted (g_variant_new_double (G_MINDOUBLE));
+  b = g_variant_new_double (G_MAXDOUBLE);
+  g_assert (g_variant_compare (a, b) < 0);
+  g_variant_unref (a);
+  g_variant_unref (b);
+  a = untrusted (g_variant_new_string ("abc"));
   b = g_variant_new_string ("abd");
   g_assert (g_variant_compare (a, b) < 0);
   g_variant_unref (a);
   g_variant_unref (b);
-  a = g_variant_new_boolean (FALSE);
+  a = untrusted (g_variant_new_object_path ("/abc"));
+  b = g_variant_new_object_path ("/abd");
+  g_assert (g_variant_compare (a, b) < 0);
+  g_variant_unref (a);
+  g_variant_unref (b);
+  a = untrusted (g_variant_new_signature ("g"));
+  b = g_variant_new_signature ("o");
+  g_assert (g_variant_compare (a, b) < 0);
+  g_variant_unref (a);
+  g_variant_unref (b);
+  a = untrusted (g_variant_new_boolean (FALSE));
   b = g_variant_new_boolean (TRUE);
   g_assert (g_variant_compare (a, b) < 0);
   g_variant_unref (a);
@@ -4105,6 +4215,79 @@ test_compare (void)
 }
 
 static void
+test_equal (void)
+{
+  GVariant *a;
+  GVariant *b;
+
+  a = untrusted (g_variant_new_byte (5));
+  b = g_variant_get_normal_form (a);
+  g_assert (g_variant_equal (a, b));
+  g_variant_unref (a);
+  g_variant_unref (b);
+  a = untrusted (g_variant_new_int16 (G_MININT16));
+  b = g_variant_get_normal_form (a);
+  g_assert (g_variant_equal (a, b));
+  g_variant_unref (a);
+  g_variant_unref (b);
+  a = untrusted (g_variant_new_uint16 (0));
+  b = g_variant_get_normal_form (a);
+  g_assert (g_variant_equal (a, b));
+  g_variant_unref (a);
+  g_variant_unref (b);
+  a = untrusted (g_variant_new_int32 (G_MININT32));
+  b = g_variant_get_normal_form (a);
+  g_assert (g_variant_equal (a, b));
+  g_variant_unref (a);
+  g_variant_unref (b);
+  a = untrusted (g_variant_new_uint32 (0));
+  b = g_variant_get_normal_form (a);
+  g_assert (g_variant_equal (a, b));
+  g_variant_unref (a);
+  g_variant_unref (b);
+  a = untrusted (g_variant_new_int64 (G_MININT64));
+  b = g_variant_get_normal_form (a);
+  g_assert (g_variant_equal (a, b));
+  g_variant_unref (a);
+  g_variant_unref (b);
+  a = untrusted (g_variant_new_uint64 (0));
+  b = g_variant_get_normal_form (a);
+  g_assert (g_variant_equal (a, b));
+  g_variant_unref (a);
+  g_variant_unref (b);
+  a = untrusted (g_variant_new_double (G_MINDOUBLE));
+  b = g_variant_get_normal_form (a);
+  g_assert (g_variant_equal (a, b));
+  g_variant_unref (a);
+  g_variant_unref (b);
+  a = untrusted (g_variant_new_string ("abc"));
+  g_assert (g_variant_equal (a, a));
+  b = g_variant_get_normal_form (a);
+  g_assert (g_variant_equal (a, b));
+  g_variant_unref (a);
+  g_variant_unref (b);
+  a = untrusted (g_variant_new_object_path ("/abc"));
+  g_assert (g_variant_equal (a, a));
+  b = g_variant_get_normal_form (a);
+  a = untrusted (a);
+  g_assert (g_variant_equal (a, b));
+  g_variant_unref (a);
+  g_variant_unref (b);
+  a = untrusted (g_variant_new_signature ("g"));
+  g_assert (g_variant_equal (a, a));
+  b = g_variant_get_normal_form (a);
+  a = untrusted (a);
+  g_assert (g_variant_equal (a, b));
+  g_variant_unref (a);
+  g_variant_unref (b);
+  a = untrusted (g_variant_new_boolean (FALSE));
+  b = g_variant_get_normal_form (a);
+  g_assert (g_variant_equal (a, b));
+  g_variant_unref (a);
+  g_variant_unref (b);
+}
+
+static void
 test_fixed_array (void)
 {
   GVariant *a;
@@ -4184,6 +4367,9 @@ test_check_format_string (void)
   g_test_assert_expected_messages ();
   g_assert (g_variant_check_format_string (value, "(s^&ay)", FALSE));
 
+  g_assert (g_variant_check_format_string (value, "r", FALSE));
+  g_assert (g_variant_check_format_string (value, "(?a?)", FALSE));
+
   g_variant_unref (value);
 }
 
@@ -4306,6 +4492,113 @@ test_gbytes (void)
   g_variant_unref (tuple);
 }
 
+typedef struct {
+  const GVariantType *type;
+  const gchar *in;
+  const gchar *out;
+} ContextTest;
+
+static void
+test_print_context (void)
+{
+  ContextTest tests[] = {
+    { NULL, "(1, 2, 3, 'abc", "          ^^^^" },
+    { NULL, "[1, 2, 3, 'str']", " ^        ^^^^^" },
+    { G_VARIANT_TYPE_UINT16, "{ 'abc':'def' }", "  ^^^^^^^^^^^^^^^" },
+    { NULL, "<5", "    ^" },
+    { NULL, "'ab\\ux'", "  ^^^^^^^" },
+    { NULL, "'ab\\U00efx'", "  ^^^^^^^^^^^" }
+  };
+  GVariant *v;
+  gchar *s;
+  gint i;
+  GError *error = NULL;
+
+  for (i = 0; i < G_N_ELEMENTS (tests); i++)
+    {
+      v = g_variant_parse (tests[i].type, tests[i].in, NULL, NULL, &error);
+      g_assert_null (v);
+      s = g_variant_parse_error_print_context (error, tests[i].in);
+      g_assert (strstr (s, tests[i].out) != NULL);
+      g_free (s);
+      g_clear_error (&error);
+    }
+}
+
+static void
+test_error_quark (void)
+{
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+  g_assert (g_variant_parser_get_error_quark () == g_variant_parse_error_quark ());
+G_GNUC_END_IGNORE_DEPRECATIONS
+}
+
+static void
+test_stack_builder_init (void)
+{
+  GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE_BYTESTRING);
+  GVariant *variant;
+
+  g_variant_builder_add_value (&builder, g_variant_new_byte ('g'));
+  g_variant_builder_add_value (&builder, g_variant_new_byte ('l'));
+  g_variant_builder_add_value (&builder, g_variant_new_byte ('i'));
+  g_variant_builder_add_value (&builder, g_variant_new_byte ('b'));
+  g_variant_builder_add_value (&builder, g_variant_new_byte ('\0'));
+
+  variant = g_variant_ref_sink (g_variant_builder_end (&builder));
+  g_assert_nonnull (variant);
+  g_assert (g_variant_type_equal (g_variant_get_type (variant),
+                                  G_VARIANT_TYPE_BYTESTRING));
+  g_assert_cmpuint (g_variant_n_children (variant), ==, 5);
+  g_assert_cmpstr (g_variant_get_bytestring (variant), ==, "glib");
+  g_variant_unref (variant);
+}
+
+static GVariant *
+get_asv (void)
+{
+  GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE_VARDICT);
+
+  g_variant_builder_add (&builder, "{s@v}", "foo", g_variant_new_variant (g_variant_new_string ("FOO")));
+  g_variant_builder_add (&builder, "{s@v}", "bar", g_variant_new_variant (g_variant_new_string ("BAR")));
+
+  return g_variant_ref_sink (g_variant_builder_end (&builder));
+}
+
+static void
+test_stack_dict_init (void)
+{
+  GVariant *asv = get_asv ();
+  GVariantDict dict = G_VARIANT_DICT_INIT (asv);
+  GVariant *variant;
+  GVariantIter iter;
+  gchar *key;
+  GVariant *value;
+
+  g_variant_dict_insert_value (&dict, "baz", g_variant_new_string ("BAZ"));
+  g_variant_dict_insert_value (&dict, "quux", g_variant_new_string ("QUUX"));
+
+  variant = g_variant_ref_sink (g_variant_dict_end (&dict));
+  g_assert_nonnull (variant);
+  g_assert (g_variant_type_equal (g_variant_get_type (variant),
+                                  G_VARIANT_TYPE_VARDICT));
+  g_assert_cmpuint (g_variant_n_children (variant), ==, 4);
+
+  g_variant_iter_init (&iter, variant);
+  while (g_variant_iter_next (&iter, "{sv}", &key, &value))
+    {
+      gchar *strup = g_ascii_strup (key, -1);
+
+      g_assert_cmpstr (strup, ==, g_variant_get_string (value, NULL));
+      g_free (key);
+      g_free (strup);
+      g_variant_unref (value);
+    }
+
+  g_variant_unref (asv);
+  g_variant_unref (variant);
+}
+
 int
 main (int argc, char **argv)
 {
@@ -4332,6 +4625,7 @@ main (int argc, char **argv)
       g_free (testname);
     }
 
+  g_test_add_func ("/gvariant/string", test_string);
   g_test_add_func ("/gvariant/utf8", test_utf8);
   g_test_add_func ("/gvariant/containers", test_containers);
   g_test_add_func ("/gvariant/format-strings", test_format_strings);
@@ -4353,6 +4647,7 @@ main (int argc, char **argv)
   g_test_add_func ("/gvariant/lookup-value", test_lookup_value);
   g_test_add_func ("/gvariant/lookup", test_lookup);
   g_test_add_func ("/gvariant/compare", test_compare);
+  g_test_add_func ("/gvariant/equal", test_equal);
   g_test_add_func ("/gvariant/fixed-array", test_fixed_array);
   g_test_add_func ("/gvariant/check-format-string", test_check_format_string);
 
@@ -4360,6 +4655,10 @@ main (int argc, char **argv)
   g_test_add_func ("/gvariant/checksum-nested", test_checksum_nested);
 
   g_test_add_func ("/gvariant/gbytes", test_gbytes);
+  g_test_add_func ("/gvariant/print-context", test_print_context);
+  g_test_add_func ("/gvariant/error-quark", test_error_quark);
 
+  g_test_add_func ("/gvariant/stack-builder-init", test_stack_builder_init);
+  g_test_add_func ("/gvariant/stack-dict-init", test_stack_dict_init);
   return g_test_run ();
 }