/* GVariant to dbus-glib escape hatch * * Copyright © 2010 Collabora Ltd. * * SPDX-License-Identifier: AFL-2.1 OR GPL-2.0-or-later OR LGPL-2.1-or-later * * Licensed under the Academic Free License version 2.1 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Alternatively, at your option, you can redistribute and/or modify * this single file under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * that license, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ #include #undef G_DISABLE_ASSERT #include #include /** * test_g_variant_equivalent: * * The function g_variant_equal() cannot be used for dictionaries because it * cares about the ordering of dictionaries, which breaks our tests. */ static gboolean test_g_variant_equivalent (GVariant *one, GVariant *two) { if (!g_variant_type_equal ( g_variant_get_type (one), g_variant_get_type (two))) { return FALSE; } else if (g_variant_is_of_type (one, G_VARIANT_TYPE_DICTIONARY) && g_variant_is_of_type (two, G_VARIANT_TYPE_DICTIONARY)) { GHashTable *hash; GVariantIter iter; GVariant *child; gboolean equal = TRUE; if (g_variant_n_children (one) != g_variant_n_children (two)) return FALSE; /* pack @one into a hash table */ hash = g_hash_table_new_full (g_variant_hash, g_variant_equal, (GDestroyNotify) g_variant_unref, (GDestroyNotify) g_variant_unref); g_variant_iter_init (&iter, one); while ((child = g_variant_iter_next_value (&iter))) { g_hash_table_insert (hash, g_variant_get_child_value (child, 0), g_variant_get_child_value (child, 1)); g_variant_unref (child); } /* now iterate @two to check for the keys in @hash */ g_variant_iter_init (&iter, two); while (equal && (child = g_variant_iter_next_value (&iter))) { GVariant *k, *v1, *v2; k = g_variant_get_child_value (child, 0); v1 = g_variant_get_child_value (child, 1); v2 = g_hash_table_lookup (hash, k); if (v2 == NULL || !test_g_variant_equivalent (v1, v2)) equal = FALSE; else g_hash_table_remove (hash, k); g_variant_unref (k); g_variant_unref (v1); g_variant_unref (child); } if (g_hash_table_size (hash) > 0) equal = FALSE; g_hash_table_destroy (hash); return equal; } else if (g_variant_is_container (one) && g_variant_is_container (two)) { guint i, size; gboolean equal = TRUE; if (g_variant_n_children (one) != g_variant_n_children (two)) return FALSE; size = g_variant_n_children (one); for (i = 0; equal && i < size; i++) { GVariant *child1, *child2; child1 = g_variant_get_child_value (one, i); child2 = g_variant_get_child_value (two, i); equal = test_g_variant_equivalent (child1, child2); g_variant_unref (child1); g_variant_unref (child2); } return equal; } else { return g_variant_equal (one, two); } } #define assert_g_variant_equivalent(a,e) \ assert_g_variant_equivalent_internal (__FILE__, __LINE__, \ #a, a, #e, e) static void assert_g_variant_equivalent_internal ( const gchar *file, gint line, const gchar *actual_name, GVariant *actual, const gchar *expected_name, GVariant *expected); static void assert_g_variant_equivalent_internal (const gchar *file, gint line, const gchar *actual_name, GVariant *actual, const gchar *expected_name, GVariant *expected) { if (!test_g_variant_equivalent (actual, expected)) { gchar *a = g_variant_print (actual, TRUE); gchar *e = g_variant_print (expected, TRUE); g_error ("%s:%d: Variants should have been equal:\n" "%s = %s\n" "%s = %s", file, line, actual_name, a, expected_name, e); /* no point in freeing the strings, we've just crashed anyway */ } } /* test_g_variant_equivalent tests */ static void test_simple_equiv (void) { GVariant *v1, *v2; v1 = g_variant_new_int32 (1984); v2 = g_variant_new_int32 (1984); g_assert_true (test_g_variant_equivalent (v1, v2)); g_variant_unref (v1); g_variant_unref (v2); } static void test_simple_not_equiv (void) { GVariant *v1, *v2; v1 = g_variant_new_int32 (1982); v2 = g_variant_new_int32 (1984); g_assert_false (test_g_variant_equivalent (v1, v2)); g_variant_unref (v1); g_variant_unref (v2); } static void test_array_not_equiv (void) { GVariantBuilder b; GVariant *v1, *v2; g_variant_builder_init (&b, G_VARIANT_TYPE ("av")); g_variant_builder_add (&b, "v", g_variant_new_int32 (1984)); g_variant_builder_add (&b, "v", g_variant_new_string ("Orwell")); g_variant_builder_add (&b, "v", g_variant_new_object_path ("/cats/escher")); v1 = g_variant_builder_end (&b); g_variant_builder_init (&b, G_VARIANT_TYPE ("av")); /* note the order has changed */ g_variant_builder_add (&b, "v", g_variant_new_string ("Orwell")); g_variant_builder_add (&b, "v", g_variant_new_int32 (1984)); g_variant_builder_add (&b, "v", g_variant_new_object_path ("/cats/escher")); v2 = g_variant_builder_end (&b); g_assert_false (test_g_variant_equivalent (v1, v2)); g_variant_unref (v1); g_variant_unref (v2); } static void test_map_equiv (void) { GVariantBuilder b; GVariant *v1, *v2; g_variant_builder_init (&b, G_VARIANT_TYPE ("a{os}")); g_variant_builder_add (&b, "{os}", "/cats/escher", "Escher Moonbeam"); g_variant_builder_add (&b, "{os}", "/cats/harvey", "Harvey Nomcat"); g_variant_builder_add (&b, "{os}", "/cats/josh", "Josh Smith"); v1 = g_variant_builder_end (&b); g_variant_builder_init (&b, G_VARIANT_TYPE ("a{os}")); /* note the order has changed */ g_variant_builder_add (&b, "{os}", "/cats/harvey", "Harvey Nomcat"); g_variant_builder_add (&b, "{os}", "/cats/escher", "Escher Moonbeam"); g_variant_builder_add (&b, "{os}", "/cats/josh", "Josh Smith"); v2 = g_variant_builder_end (&b); g_assert_true (test_g_variant_equivalent (v1, v2)); g_variant_unref (v1); g_variant_unref (v2); } static void test_map_not_equiv1 (void) { GVariantBuilder b; GVariant *v1, *v2; g_variant_builder_init (&b, G_VARIANT_TYPE ("a{os}")); g_variant_builder_add (&b, "{os}", "/cats/escher", "Escher Moonbeam"); g_variant_builder_add (&b, "{os}", "/cats/harvey", "Harvey Nomcat"); g_variant_builder_add (&b, "{os}", "/cats/josh", "Josh Smith"); v1 = g_variant_builder_end (&b); g_variant_builder_init (&b, G_VARIANT_TYPE ("a{os}")); g_variant_builder_add (&b, "{os}", "/cats/escher", "Escher Moonbeam"); g_variant_builder_add (&b, "{os}", "/cats/harvey", "Harvey Nomcat"); g_variant_builder_add (&b, "{os}", "/cats/josh", "Josh Smith"); g_variant_builder_add (&b, "{os}", "/cats/rory", "Rory Cat"); v2 = g_variant_builder_end (&b); g_assert_false (test_g_variant_equivalent (v1, v2)); g_variant_unref (v1); g_variant_unref (v2); } static void test_map_not_equiv2 (void) { GVariantBuilder b; GVariant *v1, *v2; g_variant_builder_init (&b, G_VARIANT_TYPE ("a{os}")); g_variant_builder_add (&b, "{os}", "/cats/escher", "Escher Moonbeam"); g_variant_builder_add (&b, "{os}", "/cats/harvey", "Harvey Nomcat"); g_variant_builder_add (&b, "{os}", "/cats/josh", "Josh Smith"); v1 = g_variant_builder_end (&b); g_variant_builder_init (&b, G_VARIANT_TYPE ("a{os}")); g_variant_builder_add (&b, "{os}", "/cats/escher", "Escher Moonbeam"); g_variant_builder_add (&b, "{os}", "/cats/harvey", "Harvey Nomcat"); g_variant_builder_add (&b, "{os}", "/cats/josh", "Josh Cat"); v2 = g_variant_builder_end (&b); g_assert_false (test_g_variant_equivalent (v1, v2)); g_variant_unref (v1); g_variant_unref (v2); } /* dbus_g_value_build_g_variant tests */ static void test_i (void) { GValue v = { 0, }; GVariant *var, *varc; g_value_init (&v, G_TYPE_INT); g_value_set_int (&v, 1984); var = dbus_g_value_build_g_variant (&v); g_value_unset (&v); varc = g_variant_new_int32 (1984); g_assert_true (test_g_variant_equivalent (var, varc)); g_variant_unref (var); g_variant_unref (varc); } static void test_s (void) { GValue v = { 0, }; GVariant *var, *varc; g_value_init (&v, G_TYPE_STRING); g_value_set_static_string (&v, "Orwell"); var = dbus_g_value_build_g_variant (&v); g_value_unset (&v); varc = g_variant_new_string ("Orwell"); g_assert_true (test_g_variant_equivalent (var, varc)); g_variant_unref (var); g_variant_unref (varc); } static void test_o (void) { GValue v = { 0, }; GVariant *var, *varc; g_value_init (&v, DBUS_TYPE_G_OBJECT_PATH); g_value_set_boxed (&v, "/cats/escher"); var = dbus_g_value_build_g_variant (&v); g_value_unset (&v); varc = g_variant_new_object_path ("/cats/escher"); g_assert_true (test_g_variant_equivalent (var, varc)); g_variant_unref (var); g_variant_unref (varc); } static void test_us (void) { GValue v = { 0, }; GVariant *var, *varc; GType us = dbus_g_type_get_struct ("GValueArray", G_TYPE_UINT, G_TYPE_STRING, G_TYPE_INVALID); g_value_init (&v, us); g_value_take_boxed (&v, dbus_g_type_specialized_construct (us)); dbus_g_type_struct_set (&v, 0, 1984, 1, "Orwell", G_MAXUINT); var = dbus_g_value_build_g_variant (&v); g_value_unset (&v); varc = g_variant_new ("(us)", 1984, "Orwell"); g_assert_true (test_g_variant_equivalent (var, varc)); g_variant_unref (var); g_variant_unref (varc); } static void test_a_os (void) { GValue v = { 0, }; GHashTable *map; GVariantBuilder b; GVariant *var, *varc; GType a_os = dbus_g_type_get_map ("GHashTable", DBUS_TYPE_G_OBJECT_PATH, G_TYPE_STRING); g_value_init (&v, a_os); map = dbus_g_type_specialized_construct (a_os); g_hash_table_insert (map, g_strdup ("/cats/escher"), g_strdup ("Escher Moonbeam")); g_hash_table_insert (map, g_strdup ("/cats/harvey"), g_strdup ("Harvey Nomcat")); g_hash_table_insert (map, g_strdup ("/cats/josh"), g_strdup ("Josh Smith")); g_value_take_boxed (&v, map); var = dbus_g_value_build_g_variant (&v); g_value_unset (&v); g_variant_builder_init (&b, G_VARIANT_TYPE ("a{os}")); g_variant_builder_add (&b, "{os}", "/cats/escher", "Escher Moonbeam"); g_variant_builder_add (&b, "{os}", "/cats/harvey", "Harvey Nomcat"); g_variant_builder_add (&b, "{os}", "/cats/josh", "Josh Smith"); varc = g_variant_builder_end (&b); g_assert_true (test_g_variant_equivalent (var, varc)); g_variant_unref (var); g_variant_unref (varc); } static void test_av (void) { GValue v = { 0, }, *v2; GVariantBuilder b; GVariant *var, *varc; GType av = dbus_g_type_get_collection ("GPtrArray", G_TYPE_VALUE); GPtrArray *array; g_value_init (&v, av); array = dbus_g_type_specialized_construct (av); v2 = g_new0 (GValue, 1); g_value_init (v2, G_TYPE_INT); g_value_set_int (v2, 1984); g_ptr_array_add (array, v2); v2 = g_new0 (GValue, 1); g_value_init (v2, G_TYPE_STRING); g_value_set_static_string (v2, "Orwell"); g_ptr_array_add (array, v2); v2 = g_new0 (GValue, 1); g_value_init (v2, DBUS_TYPE_G_OBJECT_PATH); g_value_set_boxed (v2, "/cats/escher"); g_ptr_array_add (array, v2); g_value_take_boxed (&v, array); var = dbus_g_value_build_g_variant (&v); g_value_unset (&v); g_variant_builder_init (&b, G_VARIANT_TYPE ("av")); g_variant_builder_add (&b, "v", g_variant_new_int32 (1984)); g_variant_builder_add (&b, "v", g_variant_new_string ("Orwell")); g_variant_builder_add (&b, "v", g_variant_new_object_path ("/cats/escher")); varc = g_variant_builder_end (&b); g_assert_true (test_g_variant_equivalent (var, varc)); g_variant_unref (var); g_variant_unref (varc); } static void test_ab (void) { GValue v = { 0, }; gboolean bools[] = { TRUE, FALSE }; GVariantBuilder b; GVariant *var, *varc; GType ab = dbus_g_type_get_collection ("GArray", G_TYPE_BOOLEAN); GArray *array; g_value_init (&v, ab); array = dbus_g_type_specialized_construct (ab); g_array_append_vals (array, bools, 2); g_assert_cmpint (g_array_index (array, gboolean, 0), ==, TRUE); g_assert_cmpint (g_array_index (array, gboolean, 1), ==, FALSE); g_value_take_boxed (&v, array); var = dbus_g_value_build_g_variant (&v); g_value_unset (&v); g_variant_builder_init (&b, G_VARIANT_TYPE ("ab")); g_variant_builder_add (&b, "b", TRUE); g_variant_builder_add (&b, "b", FALSE); varc = g_variant_builder_end (&b); g_assert_true (test_g_variant_equivalent (var, varc)); g_variant_unref (var); g_variant_unref (varc); } static void test_ai (void) { GValue v = { 0, }; gint ints[] = { 1984, 1066 }; GVariantBuilder b; GVariant *var, *varc; GType ai = dbus_g_type_get_collection ("GArray", G_TYPE_INT); GArray *array; g_value_init (&v, ai); array = dbus_g_type_specialized_construct (ai); g_array_append_vals (array, ints, 2); g_assert_cmpint (g_array_index (array, gint, 0), ==, 1984); g_assert_cmpint (g_array_index (array, gint, 1), ==, 1066); g_value_take_boxed (&v, array); var = dbus_g_value_build_g_variant (&v); g_value_unset (&v); g_variant_builder_init (&b, G_VARIANT_TYPE ("ai")); g_variant_builder_add (&b, "i", 1984); g_variant_builder_add (&b, "i", 1066); varc = g_variant_builder_end (&b); g_assert_true (test_g_variant_equivalent (var, varc)); g_variant_unref (var); g_variant_unref (varc); } static void test_au (void) { GValue v = { 0, }; guint uints[] = { 1984, 1066 }; GVariantBuilder b; GVariant *var, *varc; GType au = dbus_g_type_get_collection ("GArray", G_TYPE_UINT); GArray *array; g_value_init (&v, au); array = dbus_g_type_specialized_construct (au); g_array_append_vals (array, uints, 2); g_assert_cmpuint (g_array_index (array, guint, 0), ==, 1984); g_assert_cmpuint (g_array_index (array, guint, 1), ==, 1066); g_value_take_boxed (&v, array); var = dbus_g_value_build_g_variant (&v); g_value_unset (&v); g_variant_builder_init (&b, G_VARIANT_TYPE ("au")); g_variant_builder_add (&b, "u", 1984); g_variant_builder_add (&b, "u", 1066); varc = g_variant_builder_end (&b); g_assert_true (test_g_variant_equivalent (var, varc)); g_variant_unref (var); g_variant_unref (varc); } static void test_ax (void) { GValue v = { 0, }; gint64 ints[] = { G_GINT64_CONSTANT (-0xAAABBBBCCCCDDDD), 1066 }; GVariantBuilder b; GVariant *var, *varc; GType ax = dbus_g_type_get_collection ("GArray", G_TYPE_INT64); GArray *array; g_value_init (&v, ax); array = dbus_g_type_specialized_construct (ax); g_array_append_vals (array, ints, 2); g_assert_cmpint ((g_array_index (array, gint64, 0) / G_GINT64_CONSTANT (0x100000000)), ==, -0xAAABBBB); g_assert_cmpuint ((-(g_array_index (array, gint64, 0))) % G_GINT64_CONSTANT (0x100000000), ==, 0xCCCCDDDDu); g_assert_cmpint ((g_array_index (array, gint64, 1) / G_GINT64_CONSTANT (0x100000000)), ==, 0); g_assert_cmpuint ((g_array_index (array, gint64, 1)) % G_GINT64_CONSTANT (0x100000000), ==, 1066); g_value_take_boxed (&v, array); var = dbus_g_value_build_g_variant (&v); g_value_unset (&v); g_variant_builder_init (&b, G_VARIANT_TYPE ("ax")); g_variant_builder_add (&b, "x", G_GINT64_CONSTANT (-0xAAABBBBCCCCDDDD)); g_variant_builder_add (&b, "x", G_GINT64_CONSTANT (1066)); varc = g_variant_builder_end (&b); g_assert_true (test_g_variant_equivalent (var, varc)); g_variant_unref (var); g_variant_unref (varc); } static void test_at (void) { GValue v = { 0, }; guint64 uints[] = { G_GUINT64_CONSTANT (0xAAAABBBBCCCCDDDD), 1066 }; GVariantBuilder b; GVariant *var, *varc; GType at = dbus_g_type_get_collection ("GArray", G_TYPE_UINT64); GArray *array; g_value_init (&v, at); array = dbus_g_type_specialized_construct (at); g_array_append_vals (array, uints, 2); g_assert_cmpuint ((g_array_index (array, guint64, 0) / G_GUINT64_CONSTANT (0x100000000)), ==, 0xAAAABBBBu); g_assert_cmpuint ((g_array_index (array, guint64, 0) % G_GUINT64_CONSTANT (0x100000000)), ==, 0xCCCCDDDDu); g_assert_cmpuint ((g_array_index (array, guint64, 1) / G_GUINT64_CONSTANT (0x100000000)), ==, 0); g_assert_cmpuint ((g_array_index (array, guint64, 1) % G_GUINT64_CONSTANT (0x100000000)), ==, 1066); g_value_take_boxed (&v, array); var = dbus_g_value_build_g_variant (&v); g_value_unset (&v); g_variant_builder_init (&b, G_VARIANT_TYPE ("at")); g_variant_builder_add (&b, "t", G_GUINT64_CONSTANT (0xAAAABBBBCCCCDDDD)); g_variant_builder_add (&b, "t", G_GUINT64_CONSTANT (1066)); varc = g_variant_builder_end (&b); g_assert_true (test_g_variant_equivalent (var, varc)); g_variant_unref (var); g_variant_unref (varc); } static void test_ay (void) { GValue v = { 0, }; guchar bytes[] = { 23, 42 }; GVariantBuilder b; GVariant *var, *varc; GType ay = dbus_g_type_get_collection ("GArray", G_TYPE_UCHAR); GArray *array; g_value_init (&v, ay); array = dbus_g_type_specialized_construct (ay); g_array_append_vals (array, bytes, 2); g_assert_cmpint (g_array_index (array, guchar, 0), ==, 23); g_assert_cmpint (g_array_index (array, guchar, 1), ==, 42); g_value_take_boxed (&v, array); var = dbus_g_value_build_g_variant (&v); g_value_unset (&v); g_variant_builder_init (&b, G_VARIANT_TYPE ("ay")); g_variant_builder_add (&b, "y", 23); g_variant_builder_add (&b, "y", 42); varc = g_variant_builder_end (&b); g_assert_true (test_g_variant_equivalent (var, varc)); g_variant_unref (var); g_variant_unref (varc); } static void test_g (void) { GValue v = { 0, }; GVariant *var, *varc; g_value_init (&v, DBUS_TYPE_G_SIGNATURE); g_value_set_boxed (&v, "a{u(ua{sa{sv}})}"); var = dbus_g_value_build_g_variant (&v); g_value_unset (&v); varc = g_variant_new_signature ("a{u(ua{sa{sv}})}"); g_assert_true (test_g_variant_equivalent (var, varc)); g_variant_unref (var); g_variant_unref (varc); } static void test_roundtrip (gconstpointer user_data) { const gchar *text = user_data; GVariant *before, *after; GValue v = { 0 }; before = g_variant_new_parsed (text); dbus_g_value_parse_g_variant (before, &v); after = dbus_g_value_build_g_variant (&v); g_value_unset (&v); assert_g_variant_equivalent (before, after); g_variant_unref (before); g_variant_unref (after); } static void test_parse_basic (void) { GVariant *variant; GValue v = { 0 }; variant = g_variant_new_parsed ("'o hai'"); dbus_g_value_parse_g_variant (variant, &v); g_assert_cmpstr (G_VALUE_TYPE_NAME (&v), ==, g_type_name (G_TYPE_STRING)); g_assert_cmpstr (g_value_get_string (&v), ==, "o hai"); g_value_unset (&v); g_variant_unref (variant); variant = g_variant_new_parsed ("objectpath '/hello/world'"); dbus_g_value_parse_g_variant (variant, &v); g_assert_cmpstr (G_VALUE_TYPE_NAME (&v), ==, g_type_name (DBUS_TYPE_G_OBJECT_PATH)); g_assert_cmpstr ((gchar *) g_value_get_boxed (&v), ==, "/hello/world"); g_value_unset (&v); g_variant_unref (variant); variant = g_variant_new_parsed ("signature 'a{sv}'"); dbus_g_value_parse_g_variant (variant, &v); g_assert_cmpstr (G_VALUE_TYPE_NAME (&v), ==, g_type_name (DBUS_TYPE_G_SIGNATURE)); g_assert_cmpstr ((gchar *) g_value_get_boxed (&v), ==, "a{sv}"); g_value_unset (&v); g_variant_unref (variant); variant = g_variant_new_parsed ("23.5"); dbus_g_value_parse_g_variant (variant, &v); g_assert_cmpstr (G_VALUE_TYPE_NAME (&v), ==, g_type_name (G_TYPE_DOUBLE)); /* this is chosen to be exactly representable in binary; we use inequalities * to work around -Wfloat-equal */ g_assert_cmpfloat (g_value_get_double (&v), >=, 23.5); g_assert_cmpfloat (g_value_get_double (&v), <=, 23.5); g_value_unset (&v); g_variant_unref (variant); variant = g_variant_new_parsed ("byte 42"); dbus_g_value_parse_g_variant (variant, &v); g_assert_cmpstr (G_VALUE_TYPE_NAME (&v), ==, g_type_name (G_TYPE_UCHAR)); g_assert_cmpuint (g_value_get_uchar (&v), ==, 42); g_value_unset (&v); g_variant_unref (variant); variant = g_variant_new_parsed ("uint16 16"); dbus_g_value_parse_g_variant (variant, &v); g_assert_cmpstr (G_VALUE_TYPE_NAME (&v), ==, g_type_name (G_TYPE_UINT)); g_assert_cmpuint (g_value_get_uint (&v), ==, 16); g_value_unset (&v); g_variant_unref (variant); variant = g_variant_new_parsed ("uint32 32"); dbus_g_value_parse_g_variant (variant, &v); g_assert_cmpstr (G_VALUE_TYPE_NAME (&v), ==, g_type_name (G_TYPE_UINT)); g_assert_cmpuint (g_value_get_uint (&v), ==, 32); g_value_unset (&v); g_variant_unref (variant); variant = g_variant_new_parsed ("uint64 64"); dbus_g_value_parse_g_variant (variant, &v); g_assert_cmpstr (G_VALUE_TYPE_NAME (&v), ==, g_type_name (G_TYPE_UINT64)); g_assert_cmpuint ((guint) g_value_get_uint64 (&v), ==, 64); g_value_unset (&v); g_variant_unref (variant); variant = g_variant_new_parsed ("int16 -16"); dbus_g_value_parse_g_variant (variant, &v); g_assert_cmpstr (G_VALUE_TYPE_NAME (&v), ==, g_type_name (G_TYPE_INT)); g_assert_cmpint (g_value_get_int (&v), ==, -16); g_value_unset (&v); g_variant_unref (variant); variant = g_variant_new_parsed ("int32 -32"); dbus_g_value_parse_g_variant (variant, &v); g_assert_cmpstr (G_VALUE_TYPE_NAME (&v), ==, g_type_name (G_TYPE_INT)); g_assert_cmpint (g_value_get_int (&v), ==, -32); g_value_unset (&v); g_variant_unref (variant); variant = g_variant_new_parsed ("int64 -64"); dbus_g_value_parse_g_variant (variant, &v); g_assert_cmpstr (G_VALUE_TYPE_NAME (&v), ==, g_type_name (G_TYPE_INT64)); g_assert_cmpint ((gint) g_value_get_int64 (&v), ==, -64); g_value_unset (&v); g_variant_unref (variant); } static void test_parse_array (void) { GVariant *variant; GValue v = { 0 }; GArray *a; /* We can't test the 16-bit cases via a round-trip, because information is * lost. */ variant = g_variant_new_parsed ("[uint16 16, uint16 1600]"); dbus_g_value_parse_g_variant (variant, &v); g_assert_cmpstr (G_VALUE_TYPE_NAME (&v), ==, g_type_name (DBUS_TYPE_G_UINT_ARRAY)); a = g_value_get_boxed (&v); g_assert_cmpuint (a->len, ==, 2); g_assert_cmpuint (g_array_index (a, guint, 0), ==, 16); g_assert_cmpuint (g_array_index (a, guint, 1), ==, 1600); g_value_unset (&v); g_variant_unref (variant); variant = g_variant_new_parsed ("[int16 -16, int16 -1600]"); dbus_g_value_parse_g_variant (variant, &v); g_assert_cmpstr (G_VALUE_TYPE_NAME (&v), ==, g_type_name (DBUS_TYPE_G_INT_ARRAY)); a = g_value_get_boxed (&v); g_assert_cmpuint (a->len, ==, 2); g_assert_cmpint (g_array_index (a, gint, 0), ==, -16); g_assert_cmpint (g_array_index (a, gint, 1), ==, -1600); g_value_unset (&v); g_variant_unref (variant); variant = g_variant_new_parsed ("@aq []"); dbus_g_value_parse_g_variant (variant, &v); g_assert_cmpstr (G_VALUE_TYPE_NAME (&v), ==, g_type_name (DBUS_TYPE_G_UINT_ARRAY)); a = g_value_get_boxed (&v); g_assert_cmpuint (a->len, ==, 0); g_value_unset (&v); g_variant_unref (variant); variant = g_variant_new_parsed ("@an []"); dbus_g_value_parse_g_variant (variant, &v); g_assert_cmpstr (G_VALUE_TYPE_NAME (&v), ==, g_type_name (DBUS_TYPE_G_INT_ARRAY)); a = g_value_get_boxed (&v); g_assert_cmpuint (a->len, ==, 0); g_value_unset (&v); g_variant_unref (variant); } static void test_parse_string_hash (void) { GVariant *variant; GHashTable *h; GValue v = { 0 }; variant = g_variant_new_parsed ("@a{ss} {'foo': 'bar'}"); dbus_g_value_parse_g_variant (variant, &v); g_assert_cmpstr (G_VALUE_TYPE_NAME (&v), ==, g_type_name (DBUS_TYPE_G_STRING_STRING_HASHTABLE)); h = g_value_get_boxed (&v); g_assert_cmpuint (g_hash_table_size (h), ==, 1); g_assert_cmpstr (g_hash_table_lookup (h, "foo"), ==, "bar"); g_value_unset (&v); g_variant_unref (variant); } int main (int argc, char **argv) { g_type_init (); dbus_g_type_specialized_init (); g_test_init (&argc, &argv, NULL); /* test_g_variant_equivalent tests */ g_test_add_func ("/test_g_variant_equivalent/test_simple_equiv", test_simple_equiv); g_test_add_func ("/test_g_variant_equivalent/test_simple_not_equiv", test_simple_not_equiv); g_test_add_func ("/test_g_variant_equivalent/test_array_not_equiv", test_array_not_equiv); g_test_add_func ("/test_g_variant_equivalent/test_map_equiv", test_map_equiv); g_test_add_func ("/test_g_variant_equivalent/test_map_not_equiv1", test_map_not_equiv1); g_test_add_func ("/test_g_variant_equivalent/test_map_not_equiv2", test_map_not_equiv2); /* dbus_g_value_build_g_variant tests */ g_test_add_func ("/gvalue-to-gvariant/i", test_i); g_test_add_func ("/gvalue-to-gvariant/s", test_s); g_test_add_func ("/gvalue-to-gvariant/o", test_o); g_test_add_func ("/gvalue-to-gvariant/us", test_us); g_test_add_func ("/gvalue-to-gvariant/a{os}", test_a_os); g_test_add_func ("/gvalue-to-gvariant/av", test_av); g_test_add_func ("/gvalue-to-gvariant/ab", test_ab); g_test_add_func ("/gvalue-to-gvariant/ai", test_ai); g_test_add_func ("/gvalue-to-gvariant/au", test_au); g_test_add_func ("/gvalue-to-gvariant/ax", test_ax); g_test_add_func ("/gvalue-to-gvariant/at", test_at); g_test_add_func ("/gvalue-to-gvariant/ay", test_ay); g_test_add_func ("/gvalue-to-gvariant/g", test_g); /* dbus_g_value_parse_g_variant tests */ g_test_add_func ("/parse-gvariant/basic", test_parse_basic); g_test_add_func ("/parse-gvariant/array", test_parse_array); g_test_add_func ("/parse-gvariant/string_hash", test_parse_string_hash); /* round-trips */ g_test_add_data_func ("/parse-gvariant/roundtrip/u", "@u 42", test_roundtrip); g_test_add_data_func ("/parse-gvariant/roundtrip/non_empty_array", "@ai [23, 42]", test_roundtrip); g_test_add_data_func ("/roundtrip/empty_array", "@ai []", test_roundtrip); g_test_add_data_func ("/roundtrip/aav", "[[<'bees'>]]", test_roundtrip); g_test_add_data_func ("/roundtrip/aau", "[[uint32 666]]", test_roundtrip); g_test_add_data_func ("/roundtrip/aax", "[[int64 666]]", test_roundtrip); g_test_add_data_func ("/roundtrip/aat", "[[uint64 666]]", test_roundtrip); g_test_add_data_func ("/roundtrip/aas", "[['a', 'b']]", test_roundtrip); g_test_add_data_func ("/roundtrip/aao", "[[objectpath '/a', objectpath '/b']]", test_roundtrip); g_test_add_data_func ("/roundtrip/aag", "[[signature 'ab', signature 'g']]", test_roundtrip); g_test_add_data_func ("/roundtrip/aad", "[[5.25, 3.5]]", test_roundtrip); g_test_add_data_func ("/roundtrip/aay", "@aay [[1, 2]]", test_roundtrip); g_test_add_data_func ("/roundtrip/empty_aay", "@aay [[]]", test_roundtrip); g_test_add_data_func ("/roundtrip/aab", "[[true, false]]", test_roundtrip); g_test_add_data_func ("/roundtrip/empty_aab", "@aab [[]]", test_roundtrip); g_test_add_data_func ("/roundtrip/aa_asv", "[[@a{sv} {'x': <'y'>}]]", test_roundtrip); g_test_add_data_func ("/roundtrip/empty_av", "@av []", test_roundtrip); g_test_add_data_func ("/roundtrip/empty_hash", "@a{uu} {}", test_roundtrip); g_test_add_data_func ("/roundtrip/easy_string_hash", "@a{ss} {'foo': 'bar'}", test_roundtrip); g_test_add_data_func ("/roundtrip/non_empty_asv", "@a{sv} {'badger': <42>, 'mushroom': , 'snake': <''>}", test_roundtrip); g_test_add_data_func ("/roundtrip/variant_nesting", "<<<42>>>", test_roundtrip); g_test_add_data_func ("/roundtrip/tuple", "(23, 42, true)", test_roundtrip); g_test_add_data_func ("/roundtrip/nested", "[[[(1, 2)]]]", test_roundtrip); g_test_add_data_func ("/roundtrip/empty_aaa", "@aaav [[]]", test_roundtrip); g_test_add_data_func ("/roundtrip/empty_aa_asv", "@aaa{sv} [[]]", test_roundtrip); g_test_add_data_func ("/roundtrip/empty_aa_struct", "@aa(us) [[]]", test_roundtrip); g_test_add_data_func ("/roundtrip/empty_aaas", "@aaas [[]]", test_roundtrip); g_test_add_data_func ("/roundtrip/empty_aax", "@aax [[]]", test_roundtrip); g_test_add_data_func ("/roundtrip/empty_aat", "@aat [[]]", test_roundtrip); g_test_add_data_func ("/roundtrip/empty_aad", "@aad [[]]", test_roundtrip); g_test_add_data_func ("/roundtrip/empty_aao", "@aao [[]]", test_roundtrip); g_test_add_data_func ("/roundtrip/empty_aag", "@aag [[]]", test_roundtrip); return g_test_run (); }