X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gio%2Ftests%2Fgdbus-export.c;h=75020234a24cad1245fe8a49ade0ae249f39fbfc;hb=634b69219979c084837c59874e5b2aec01a1d3e4;hp=6e33d2f4fe9f51318a4aec5998e7b6ed71472bc6;hpb=d0a14469d09d5fe23de219ba293fd4a266b02ced;p=platform%2Fupstream%2Fglib.git diff --git a/gio/tests/gdbus-export.c b/gio/tests/gdbus-export.c index 6e33d2f..7502023 100644 --- a/gio/tests/gdbus-export.c +++ b/gio/tests/gdbus-export.c @@ -1,6 +1,6 @@ /* GLib testing framework examples and tests * - * Copyright (C) 2008-2009 Red Hat, Inc. + * Copyright (C) 2008-2010 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -13,9 +13,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. + * Public License along with this library; if not, see . * * Author: David Zeuthen */ @@ -122,6 +120,15 @@ static const GDBusInterfaceInfo foo_interface_info = NULL, }; +/* Foo2 is just Foo without the properties */ +static const GDBusInterfaceInfo foo2_interface_info = +{ + -1, + "org.example.Foo2", + (GDBusMethodInfo **) &foo_method_info_pointers, + (GDBusSignalInfo **) &foo_signal_info_pointers, +}; + static void foo_method_call (GDBusConnection *connection, const gchar *sender, @@ -136,8 +143,8 @@ foo_method_call (GDBusConnection *connection, { const gchar *input; gchar *output; - g_variant_get (parameters, "(s)", &input); - output = g_strdup_printf ("You passed the string `%s'. Jolly good!", input); + g_variant_get (parameters, "(&s)", &input); + output = g_strdup_printf ("You passed the string '%s'. Jolly good!", input); g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", output)); g_free (output); } @@ -160,7 +167,7 @@ foo_get_property (GDBusConnection *connection, { GVariant *ret; gchar *s; - s = g_strdup_printf ("Property `%s' Is What It Is!", property_name); + s = g_strdup_printf ("Property '%s' Is What It Is!", property_name); ret = g_variant_new_string (s); g_free (s); return ret; @@ -181,7 +188,7 @@ foo_set_property (GDBusConnection *connection, g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_SPAWN_FILE_INVALID, - "Returning some error instead of writing the value `%s' to the property `%s'", + "Returning some error instead of writing the value '%s' to the property '%s'", property_name, s); g_free (s); return FALSE; @@ -314,19 +321,17 @@ introspect_callback (GDBusProxy *proxy, GAsyncResult *res, gpointer user_data) { - const gchar *s; gchar **xml_data = user_data; GVariant *result; GError *error; error = NULL; - result = g_dbus_proxy_invoke_method_finish (proxy, + result = g_dbus_proxy_call_finish (proxy, res, &error); g_assert_no_error (error); g_assert (result != NULL); - g_variant_get (result, "(s)", &s); - *xml_data = g_strdup (s); + g_variant_get (result, "(s)", xml_data); g_variant_unref (result); g_main_loop_quit (loop); @@ -345,7 +350,6 @@ get_nodes_at (GDBusConnection *c, error = NULL; proxy = g_dbus_proxy_new_sync (c, - G_TYPE_DBUS_PROXY, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, NULL, @@ -359,14 +363,14 @@ get_nodes_at (GDBusConnection *c, /* do this async to avoid libdbus-1 deadlocks */ xml_data = NULL; - g_dbus_proxy_invoke_method (proxy, - "Introspect", - NULL, - G_DBUS_INVOKE_METHOD_FLAGS_NONE, - -1, - NULL, - (GAsyncReadyCallback) introspect_callback, - &xml_data); + g_dbus_proxy_call (proxy, + "Introspect", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + (GAsyncReadyCallback) introspect_callback, + &xml_data); g_main_loop_run (loop); g_assert (xml_data != NULL); @@ -402,7 +406,6 @@ has_interface (GDBusConnection *c, error = NULL; proxy = g_dbus_proxy_new_sync (c, - G_TYPE_DBUS_PROXY, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, NULL, @@ -416,14 +419,14 @@ has_interface (GDBusConnection *c, /* do this async to avoid libdbus-1 deadlocks */ xml_data = NULL; - g_dbus_proxy_invoke_method (proxy, - "Introspect", - NULL, - G_DBUS_INVOKE_METHOD_FLAGS_NONE, - -1, - NULL, - (GAsyncReadyCallback) introspect_callback, - &xml_data); + g_dbus_proxy_call (proxy, + "Introspect", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + (GAsyncReadyCallback) introspect_callback, + &xml_data); g_main_loop_run (loop); g_assert (xml_data != NULL); @@ -452,7 +455,6 @@ count_interfaces (GDBusConnection *c, error = NULL; proxy = g_dbus_proxy_new_sync (c, - G_TYPE_DBUS_PROXY, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, NULL, @@ -466,14 +468,14 @@ count_interfaces (GDBusConnection *c, /* do this async to avoid libdbus-1 deadlocks */ xml_data = NULL; - g_dbus_proxy_invoke_method (proxy, - "Introspect", - NULL, - G_DBUS_INVOKE_METHOD_FLAGS_NONE, - -1, - NULL, - (GAsyncReadyCallback) introspect_callback, - &xml_data); + g_dbus_proxy_call (proxy, + "Introspect", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + (GAsyncReadyCallback) introspect_callback, + &xml_data); g_main_loop_run (loop); g_assert (xml_data != NULL); @@ -501,9 +503,9 @@ dyna_create_callback (GDBusProxy *proxy, GError *error; error = NULL; - result = g_dbus_proxy_invoke_method_finish (proxy, - res, - &error); + result = g_dbus_proxy_call_finish (proxy, + res, + &error); g_assert_no_error (error); g_assert (result != NULL); g_variant_unref (result); @@ -524,7 +526,6 @@ dyna_create (GDBusConnection *c, error = NULL; proxy = g_dbus_proxy_new_sync (c, - G_TYPE_DBUS_PROXY, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, NULL, @@ -537,14 +538,14 @@ dyna_create (GDBusConnection *c, g_assert (proxy != NULL); /* do this async to avoid libdbus-1 deadlocks */ - g_dbus_proxy_invoke_method (proxy, - "DynaCyber", - g_variant_new ("()"), - G_DBUS_INVOKE_METHOD_FLAGS_NONE, - -1, - NULL, - (GAsyncReadyCallback) dyna_create_callback, - NULL); + g_dbus_proxy_call (proxy, + "DynaCyber", + g_variant_new ("()"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + (GAsyncReadyCallback) dyna_create_callback, + NULL); g_main_loop_run (loop); g_assert_no_error (error); @@ -620,37 +621,38 @@ subtree_enumerate (GDBusConnection *connection, } /* Only allows certain objects, and aborts on unknowns */ -static GPtrArray * +static GDBusInterfaceInfo ** subtree_introspect (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *node, gpointer user_data) { - GPtrArray *interfaces; + const GDBusInterfaceInfo *interfaces[2] = { + NULL /* filled in below */, NULL + }; /* VPs implement the Foo interface, EVPs implement the Bar interface. The root * does not implement any interfaces */ - interfaces = g_ptr_array_new (); - if (g_str_has_prefix (node, "vp")) + if (node == NULL) { - g_ptr_array_add (interfaces, (gpointer) &foo_interface_info); + return NULL; } - else if (g_str_has_prefix (node, "evp")) + else if (g_str_has_prefix (node, "vp")) { - g_ptr_array_add (interfaces, (gpointer) &bar_interface_info); + interfaces[0] = &foo_interface_info; } - else if (g_strcmp0 (node, "/") == 0) + else if (g_str_has_prefix (node, "evp")) { - /* do nothing */ + interfaces[0] = &bar_interface_info; } else { g_assert_not_reached (); } - return interfaces; + return g_memdup (interfaces, 2 * sizeof (void *)); } static const GDBusInterfaceVTable * @@ -697,20 +699,16 @@ dynamic_subtree_enumerate (GDBusConnection *connection, } /* Allow all objects to be introspected */ -static GPtrArray * +static GDBusInterfaceInfo ** dynamic_subtree_introspect (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *node, gpointer user_data) { - GPtrArray *interfaces; + const GDBusInterfaceInfo *interfaces[2] = { &dyna_interface_info, NULL }; - /* All nodes (including the root node) implements the Dyna interface */ - interfaces = g_ptr_array_new (); - g_ptr_array_add (interfaces, (gpointer) &dyna_interface_info); - - return interfaces; + return g_memdup (interfaces, 2 * sizeof (void *)); } static const GDBusInterfaceVTable * @@ -747,7 +745,6 @@ test_dispatch_thread_func (gpointer user_data) const gchar *value_str; foo_proxy = g_dbus_proxy_new_sync (c, - G_TYPE_DBUS_PROXY, G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS | G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL, @@ -760,167 +757,180 @@ test_dispatch_thread_func (gpointer user_data) /* generic interfaces */ error = NULL; - value = g_dbus_proxy_invoke_method_sync (foo_proxy, - "org.freedesktop.DBus.Peer.Ping", - NULL, - G_DBUS_INVOKE_METHOD_FLAGS_NONE, - -1, - NULL, - &error); + value = g_dbus_proxy_call_sync (foo_proxy, + "org.freedesktop.DBus.Peer.Ping", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); g_assert_no_error (error); g_assert (value != NULL); g_variant_unref (value); /* user methods */ error = NULL; - value = g_dbus_proxy_invoke_method_sync (foo_proxy, - "Method1", - g_variant_new ("(s)", "winwinwin"), - G_DBUS_INVOKE_METHOD_FLAGS_NONE, - -1, - NULL, - &error); + value = g_dbus_proxy_call_sync (foo_proxy, + "Method1", + g_variant_new ("(s)", "winwinwin"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); g_assert_no_error (error); g_assert (value != NULL); g_assert (g_variant_is_of_type (value, G_VARIANT_TYPE ("(s)"))); - g_variant_get (value, "(s)", &value_str); - g_assert_cmpstr (value_str, ==, "You passed the string `winwinwin'. Jolly good!"); + g_variant_get (value, "(&s)", &value_str); + g_assert_cmpstr (value_str, ==, "You passed the string 'winwinwin'. Jolly good!"); g_variant_unref (value); error = NULL; - value = g_dbus_proxy_invoke_method_sync (foo_proxy, - "Method2", - NULL, - G_DBUS_INVOKE_METHOD_FLAGS_NONE, - -1, - NULL, - &error); + value = g_dbus_proxy_call_sync (foo_proxy, + "Method2", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR); g_assert_cmpstr (error->message, ==, "GDBus.Error:org.example.SomeError: How do you like them apples, buddy!"); g_error_free (error); g_assert (value == NULL); error = NULL; - value = g_dbus_proxy_invoke_method_sync (foo_proxy, - "Method2", - g_variant_new ("(s)", "failfailfail"), - G_DBUS_INVOKE_METHOD_FLAGS_NONE, - -1, - NULL, - &error); + value = g_dbus_proxy_call_sync (foo_proxy, + "Method2", + g_variant_new ("(s)", "failfailfail"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS); - g_assert_cmpstr (error->message, ==, "GDBus.Error:org.freedesktop.DBus.Error.InvalidArgs: Signature of message, `s', does not match expected signature `'"); + g_assert_cmpstr (error->message, ==, "GDBus.Error:org.freedesktop.DBus.Error.InvalidArgs: Type of message, '(s)', does not match expected type '()'"); g_error_free (error); g_assert (value == NULL); error = NULL; - value = g_dbus_proxy_invoke_method_sync (foo_proxy, - "NonExistantMethod", - NULL, - G_DBUS_INVOKE_METHOD_FLAGS_NONE, - -1, - NULL, - &error); + value = g_dbus_proxy_call_sync (foo_proxy, + "NonExistantMethod", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD); + g_assert_cmpstr (error->message, ==, "GDBus.Error:org.freedesktop.DBus.Error.UnknownMethod: No such method 'NonExistantMethod'"); + g_error_free (error); + g_assert (value == NULL); + + error = NULL; + value = g_dbus_proxy_call_sync (foo_proxy, + "org.example.FooXYZ.NonExistant", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD); - g_assert_cmpstr (error->message, ==, "GDBus.Error:org.freedesktop.DBus.Error.UnknownMethod: No such method `NonExistantMethod'"); g_error_free (error); g_assert (value == NULL); /* user properties */ error = NULL; - value = g_dbus_proxy_invoke_method_sync (foo_proxy, - "org.freedesktop.DBus.Properties.Get", - g_variant_new ("(ss)", - "org.example.Foo", - "PropertyUno"), - G_DBUS_INVOKE_METHOD_FLAGS_NONE, - -1, - NULL, - &error); + value = g_dbus_proxy_call_sync (foo_proxy, + "org.freedesktop.DBus.Properties.Get", + g_variant_new ("(ss)", + "org.example.Foo", + "PropertyUno"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); g_assert_no_error (error); g_assert (value != NULL); g_assert (g_variant_is_of_type (value, G_VARIANT_TYPE ("(v)"))); g_variant_get (value, "(v)", &inner); g_assert (g_variant_is_of_type (inner, G_VARIANT_TYPE_STRING)); - g_assert_cmpstr (g_variant_get_string (inner, NULL), ==, "Property `PropertyUno' Is What It Is!"); + g_assert_cmpstr (g_variant_get_string (inner, NULL), ==, "Property 'PropertyUno' Is What It Is!"); g_variant_unref (value); + g_variant_unref (inner); error = NULL; - value = g_dbus_proxy_invoke_method_sync (foo_proxy, - "org.freedesktop.DBus.Properties.Get", - g_variant_new ("(ss)", - "org.example.Foo", - "ThisDoesntExist"), - G_DBUS_INVOKE_METHOD_FLAGS_NONE, - -1, - NULL, - &error); + value = g_dbus_proxy_call_sync (foo_proxy, + "org.freedesktop.DBus.Properties.Get", + g_variant_new ("(ss)", + "org.example.Foo", + "ThisDoesntExist"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); g_assert (value == NULL); g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS); - g_assert_cmpstr (error->message, ==, "GDBus.Error:org.freedesktop.DBus.Error.InvalidArgs: No such property `ThisDoesntExist'"); + g_assert_cmpstr (error->message, ==, "GDBus.Error:org.freedesktop.DBus.Error.InvalidArgs: No such property 'ThisDoesntExist'"); g_error_free (error); error = NULL; - value = g_dbus_proxy_invoke_method_sync (foo_proxy, - "org.freedesktop.DBus.Properties.Get", - g_variant_new ("(ss)", - "org.example.Foo", - "NotReadable"), - G_DBUS_INVOKE_METHOD_FLAGS_NONE, - -1, - NULL, - &error); + value = g_dbus_proxy_call_sync (foo_proxy, + "org.freedesktop.DBus.Properties.Get", + g_variant_new ("(ss)", + "org.example.Foo", + "NotReadable"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); g_assert (value == NULL); g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS); - g_assert_cmpstr (error->message, ==, "GDBus.Error:org.freedesktop.DBus.Error.InvalidArgs: Property `NotReadable' is not readable"); + g_assert_cmpstr (error->message, ==, "GDBus.Error:org.freedesktop.DBus.Error.InvalidArgs: Property 'NotReadable' is not readable"); g_error_free (error); error = NULL; - value = g_dbus_proxy_invoke_method_sync (foo_proxy, - "org.freedesktop.DBus.Properties.Set", - g_variant_new ("(ssv)", - "org.example.Foo", - "NotReadable", - g_variant_new_string ("But Writable you are!")), - G_DBUS_INVOKE_METHOD_FLAGS_NONE, - -1, - NULL, - &error); + value = g_dbus_proxy_call_sync (foo_proxy, + "org.freedesktop.DBus.Properties.Set", + g_variant_new ("(ssv)", + "org.example.Foo", + "NotReadable", + g_variant_new_string ("But Writable you are!")), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); g_assert (value == NULL); g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_SPAWN_FILE_INVALID); - g_assert_cmpstr (error->message, ==, "GDBus.Error:org.freedesktop.DBus.Error.Spawn.FileInvalid: Returning some error instead of writing the value `NotReadable' to the property `'But Writable you are!''"); + g_assert_cmpstr (error->message, ==, "GDBus.Error:org.freedesktop.DBus.Error.Spawn.FileInvalid: Returning some error instead of writing the value 'NotReadable' to the property ''But Writable you are!''"); g_error_free (error); error = NULL; - value = g_dbus_proxy_invoke_method_sync (foo_proxy, - "org.freedesktop.DBus.Properties.Set", - g_variant_new ("(ssv)", - "org.example.Foo", - "NotWritable", - g_variant_new_uint32 (42)), - G_DBUS_INVOKE_METHOD_FLAGS_NONE, - -1, - NULL, - &error); + value = g_dbus_proxy_call_sync (foo_proxy, + "org.freedesktop.DBus.Properties.Set", + g_variant_new ("(ssv)", + "org.example.Foo", + "NotWritable", + g_variant_new_uint32 (42)), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); g_assert (value == NULL); g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS); - g_assert_cmpstr (error->message, ==, "GDBus.Error:org.freedesktop.DBus.Error.InvalidArgs: Property `NotWritable' is not writable"); + g_assert_cmpstr (error->message, ==, "GDBus.Error:org.freedesktop.DBus.Error.InvalidArgs: Property 'NotWritable' is not writable"); g_error_free (error); error = NULL; - value = g_dbus_proxy_invoke_method_sync (foo_proxy, - "org.freedesktop.DBus.Properties.GetAll", - g_variant_new ("(s)", - "org.example.Foo"), - G_DBUS_INVOKE_METHOD_FLAGS_NONE, - -1, - NULL, - &error); + value = g_dbus_proxy_call_sync (foo_proxy, + "org.freedesktop.DBus.Properties.GetAll", + g_variant_new ("(s)", + "org.example.Foo"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); g_assert_no_error (error); g_assert (value != NULL); g_assert (g_variant_is_of_type (value, G_VARIANT_TYPE ("(a{sv})"))); s = g_variant_print (value, TRUE); - g_assert_cmpstr (s, ==, "({'PropertyUno': <\"Property `PropertyUno' Is What It Is!\">, 'NotWritable': <\"Property `NotWritable' Is What It Is!\">},)"); + g_assert_cmpstr (s, ==, "({'PropertyUno': <\"Property 'PropertyUno' Is What It Is!\">, 'NotWritable': <\"Property 'NotWritable' Is What It Is!\">},)"); g_free (s); g_variant_unref (value); @@ -934,16 +944,11 @@ static void test_dispatch (const gchar *object_path) { GThread *thread; - GError *error; /* run this in a thread to avoid deadlocks */ - error = NULL; - thread = g_thread_create (test_dispatch_thread_func, - (gpointer) object_path, - TRUE, - &error); - g_assert_no_error (error); - g_assert (thread != NULL); + thread = g_thread_new ("test_dispatch", + test_dispatch_thread_func, + (gpointer) object_path); g_main_loop_run (loop); g_thread_join (thread); } @@ -958,6 +963,7 @@ test_object_registration (void) guint boss_foo_reg_id; guint boss_bar_reg_id; guint worker1_foo_reg_id; + guint worker1p1_foo_reg_id; guint worker2_bar_reg_id; guint intern1_foo_reg_id; guint intern2_bar_reg_id; @@ -983,8 +989,7 @@ test_object_registration (void) registration_id = g_dbus_connection_register_object (c, "/foo/boss", - foo_interface_info.name, - &foo_interface_info, + (GDBusInterfaceInfo *) &foo_interface_info, &foo_vtable, &data, on_object_unregistered, @@ -996,8 +1001,7 @@ test_object_registration (void) registration_id = g_dbus_connection_register_object (c, "/foo/boss", - bar_interface_info.name, - &bar_interface_info, + (GDBusInterfaceInfo *) &bar_interface_info, NULL, &data, on_object_unregistered, @@ -1009,8 +1013,7 @@ test_object_registration (void) registration_id = g_dbus_connection_register_object (c, "/foo/boss/worker1", - foo_interface_info.name, - &foo_interface_info, + (GDBusInterfaceInfo *) &foo_interface_info, NULL, &data, on_object_unregistered, @@ -1021,9 +1024,20 @@ test_object_registration (void) num_successful_registrations++; registration_id = g_dbus_connection_register_object (c, + "/foo/boss/worker1p1", + (GDBusInterfaceInfo *) &foo_interface_info, + NULL, + &data, + on_object_unregistered, + &error); + g_assert_no_error (error); + g_assert (registration_id > 0); + worker1p1_foo_reg_id = registration_id; + num_successful_registrations++; + + registration_id = g_dbus_connection_register_object (c, "/foo/boss/worker2", - bar_interface_info.name, - &bar_interface_info, + (GDBusInterfaceInfo *) &bar_interface_info, NULL, &data, on_object_unregistered, @@ -1035,8 +1049,7 @@ test_object_registration (void) registration_id = g_dbus_connection_register_object (c, "/foo/boss/interns/intern1", - foo_interface_info.name, - &foo_interface_info, + (GDBusInterfaceInfo *) &foo_interface_info, NULL, &data, on_object_unregistered, @@ -1049,8 +1062,7 @@ test_object_registration (void) /* ... and try again at another path */ registration_id = g_dbus_connection_register_object (c, "/foo/boss/interns/intern2", - bar_interface_info.name, - &bar_interface_info, + (GDBusInterfaceInfo *) &bar_interface_info, NULL, &data, on_object_unregistered, @@ -1063,8 +1075,7 @@ test_object_registration (void) /* register at the same path/interface - this should fail */ registration_id = g_dbus_connection_register_object (c, "/foo/boss/interns/intern2", - bar_interface_info.name, - &bar_interface_info, + (GDBusInterfaceInfo *) &bar_interface_info, NULL, &data, on_object_unregistered, @@ -1078,8 +1089,7 @@ test_object_registration (void) /* register at different interface - shouldn't fail */ registration_id = g_dbus_connection_register_object (c, "/foo/boss/interns/intern2", - foo_interface_info.name, - &foo_interface_info, + (GDBusInterfaceInfo *) &foo_interface_info, NULL, &data, on_object_unregistered, @@ -1091,14 +1101,14 @@ test_object_registration (void) /* unregister it via the id */ g_assert (g_dbus_connection_unregister_object (c, registration_id)); + g_main_context_iteration (NULL, FALSE); g_assert_cmpint (data.num_unregistered_calls, ==, 1); intern2_foo_reg_id = 0; /* register it back */ registration_id = g_dbus_connection_register_object (c, "/foo/boss/interns/intern2", - foo_interface_info.name, - &foo_interface_info, + (GDBusInterfaceInfo *) &foo_interface_info, NULL, &data, on_object_unregistered, @@ -1110,8 +1120,7 @@ test_object_registration (void) registration_id = g_dbus_connection_register_object (c, "/foo/boss/interns/intern3", - bar_interface_info.name, - &bar_interface_info, + (GDBusInterfaceInfo *) &bar_interface_info, NULL, &data, on_object_unregistered, @@ -1148,6 +1157,7 @@ test_object_registration (void) /* unregister it, then register it again */ g_assert_cmpint (data.num_unregistered_subtree_calls, ==, 0); g_assert (g_dbus_connection_unregister_subtree (c, subtree_registration_id)); + g_main_context_iteration (NULL, FALSE); g_assert_cmpint (data.num_unregistered_subtree_calls, ==, 1); subtree_registration_id = g_dbus_connection_register_subtree (c, "/foo/boss/executives", @@ -1167,8 +1177,7 @@ test_object_registration (void) */ registration_id = g_dbus_connection_register_object (c, "/foo/boss/executives/non_subtree_object", - bar_interface_info.name, - &bar_interface_info, + (GDBusInterfaceInfo *) &bar_interface_info, NULL, &data, on_object_unregistered, @@ -1179,8 +1188,7 @@ test_object_registration (void) num_successful_registrations++; registration_id = g_dbus_connection_register_object (c, "/foo/boss/executives/non_subtree_object", - foo_interface_info.name, - &foo_interface_info, + (GDBusInterfaceInfo *) &foo_interface_info, NULL, &data, on_object_unregistered, @@ -1191,7 +1199,7 @@ test_object_registration (void) num_successful_registrations++; /* now register a dynamic subtree, spawning objects as they are called */ - dyna_data = g_ptr_array_new (); + dyna_data = g_ptr_array_new_with_free_func (g_free); dyna_subtree_registration_id = g_dbus_connection_register_subtree (c, "/foo/dyna", &dynamic_subtree_vtable, @@ -1211,9 +1219,9 @@ test_object_registration (void) /* Install three nodes in the dynamic subtree via the dyna_data backdoor and * assert that they show up correctly in the introspection data */ - g_ptr_array_add (dyna_data, "lol"); - g_ptr_array_add (dyna_data, "cat"); - g_ptr_array_add (dyna_data, "cheezburger"); + g_ptr_array_add (dyna_data, g_strdup ("lol")); + g_ptr_array_add (dyna_data, g_strdup ("cat")); + g_ptr_array_add (dyna_data, g_strdup ("cheezburger")); nodes = get_nodes_at (c, "/foo/dyna"); g_assert (nodes != NULL); g_assert_cmpint (g_strv_length (nodes), ==, 3); @@ -1257,8 +1265,9 @@ test_object_registration (void) nodes = get_nodes_at (c, "/foo/boss"); g_assert (nodes != NULL); - g_assert_cmpint (g_strv_length (nodes), ==, 4); + g_assert_cmpint (g_strv_length (nodes), ==, 5); g_assert (_g_strv_has_string ((const gchar* const *) nodes, "worker1")); + g_assert (_g_strv_has_string ((const gchar* const *) nodes, "worker1p1")); g_assert (_g_strv_has_string ((const gchar* const *) nodes, "worker2")); g_assert (_g_strv_has_string ((const gchar* const *) nodes, "interns")); g_assert (_g_strv_has_string ((const gchar* const *) nodes, "executives")); @@ -1318,6 +1327,17 @@ test_object_registration (void) g_assert (_g_strv_has_string ((const gchar* const *) nodes, "evp2")); g_strfreev (nodes); + /* This is to check that a bug (rather, class of bugs) in gdbusconnection.c's + * + * g_dbus_connection_list_registered_unlocked() + * + * where /foo/boss/worker1 reported a child '1', is now fixed. + */ + nodes = get_nodes_at (c, "/foo/boss/worker1"); + g_assert (nodes != NULL); + g_assert_cmpint (g_strv_length (nodes), ==, 0); + g_strfreev (nodes); + /* check that calls are properly dispatched to the functions in foo_vtable for objects * implementing the org.example.Foo interface * @@ -1329,13 +1349,14 @@ test_object_registration (void) /* To prevent from exiting and attaching a D-Bus tool like D-Feet; uncomment: */ #if 0 - g_debug ("Point D-feet or other tool at: %s", session_bus_get_temporary_address()); + g_debug ("Point D-feet or other tool at: %s", g_test_dbus_get_temporary_address()); g_main_loop_run (loop); #endif /* check that unregistering the subtree handler works */ g_assert_cmpint (data.num_unregistered_subtree_calls, ==, 1); g_assert (g_dbus_connection_unregister_subtree (c, subtree_registration_id)); + g_main_context_iteration (NULL, FALSE); g_assert_cmpint (data.num_unregistered_subtree_calls, ==, 2); nodes = get_nodes_at (c, "/foo/boss/executives"); g_assert (nodes != NULL); @@ -1346,6 +1367,7 @@ test_object_registration (void) g_assert (g_dbus_connection_unregister_object (c, boss_foo_reg_id)); g_assert (g_dbus_connection_unregister_object (c, boss_bar_reg_id)); g_assert (g_dbus_connection_unregister_object (c, worker1_foo_reg_id)); + g_assert (g_dbus_connection_unregister_object (c, worker1p1_foo_reg_id)); g_assert (g_dbus_connection_unregister_object (c, worker2_bar_reg_id)); g_assert (g_dbus_connection_unregister_object (c, intern1_foo_reg_id)); g_assert (g_dbus_connection_unregister_object (c, intern2_bar_reg_id)); @@ -1354,6 +1376,7 @@ test_object_registration (void) g_assert (g_dbus_connection_unregister_object (c, non_subtree_object_path_bar_reg_id)); g_assert (g_dbus_connection_unregister_object (c, non_subtree_object_path_foo_reg_id)); + g_main_context_iteration (NULL, FALSE); g_assert_cmpint (data.num_unregistered_calls, ==, num_successful_registrations); /* check that we no longer export any objects - TODO: it looks like there's a bug in @@ -1369,6 +1392,337 @@ test_object_registration (void) g_object_unref (c); } +static const GDBusInterfaceInfo test_interface_info1 = +{ + -1, + "org.example.Foo", + (GDBusMethodInfo **) NULL, + (GDBusSignalInfo **) NULL, + (GDBusPropertyInfo **) NULL, + NULL, +}; + +static const GDBusInterfaceInfo test_interface_info2 = +{ + -1, + "org.freedesktop.DBus.Properties", + (GDBusMethodInfo **) NULL, + (GDBusSignalInfo **) NULL, + (GDBusPropertyInfo **) NULL, + NULL, +}; + +static void +check_interfaces (GDBusConnection *c, + const gchar *object_path, + const gchar **interfaces) +{ + GError *error; + GDBusProxy *proxy; + gchar *xml_data; + GDBusNodeInfo *node_info; + gint i, j; + + error = NULL; + proxy = g_dbus_proxy_new_sync (c, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | + G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, + NULL, + g_dbus_connection_get_unique_name (c), + object_path, + "org.freedesktop.DBus.Introspectable", + NULL, + &error); + g_assert_no_error (error); + g_assert (proxy != NULL); + + /* do this async to avoid libdbus-1 deadlocks */ + xml_data = NULL; + g_dbus_proxy_call (proxy, + "Introspect", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + (GAsyncReadyCallback) introspect_callback, + &xml_data); + g_main_loop_run (loop); + g_assert (xml_data != NULL); + + node_info = g_dbus_node_info_new_for_xml (xml_data, &error); + g_assert_no_error (error); + g_assert (node_info != NULL); + + g_assert (node_info->interfaces != NULL); + for (i = 0; node_info->interfaces[i]; i++) ; +#if 0 + if (g_strv_length ((gchar**)interfaces) != i - 1) + { + g_print ("expected "); + for (i = 0; interfaces[i]; i++) + g_print ("%s ", interfaces[i]); + g_print ("\ngot "); + for (i = 0; node_info->interfaces[i]; i++) + g_print ("%s ", node_info->interfaces[i]->name); + g_print ("\n"); + } +#endif + g_assert_cmpint (g_strv_length ((gchar**)interfaces), ==, i - 1); + + for (i = 0; interfaces[i]; i++) + { + for (j = 0; node_info->interfaces[j]; j++) + { + if (strcmp (interfaces[i], node_info->interfaces[j]->name) == 0) + goto found; + } + + g_assert_not_reached (); + + found: ; + } + + g_object_unref (proxy); + g_free (xml_data); + g_dbus_node_info_unref (node_info); +} + +static void +test_registered_interfaces (void) +{ + GError *error; + guint id1, id2; + const gchar *interfaces[] = { + "org.example.Foo", + "org.freedesktop.DBus.Properties", + "org.freedesktop.DBus.Introspectable", + NULL, + }; + + error = NULL; + c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); + g_assert_no_error (error); + g_assert (c != NULL); + + id1 = g_dbus_connection_register_object (c, + "/test", + (GDBusInterfaceInfo *) &test_interface_info1, + NULL, + NULL, + NULL, + &error); + g_assert_no_error (error); + g_assert (id1 > 0); + id2 = g_dbus_connection_register_object (c, + "/test", + (GDBusInterfaceInfo *) &test_interface_info2, + NULL, + NULL, + NULL, + &error); + g_assert_no_error (error); + g_assert (id2 > 0); + + check_interfaces (c, "/test", interfaces); + + g_assert (g_dbus_connection_unregister_object (c, id1)); + g_assert (g_dbus_connection_unregister_object (c, id2)); + g_object_unref (c); +} + + +/* ---------------------------------------------------------------------------------------------------- */ + +static void +test_async_method_call (GDBusConnection *connection, + const gchar *sender, + const gchar *object_path, + const gchar *interface_name, + const gchar *method_name, + GVariant *parameters, + GDBusMethodInvocation *invocation, + gpointer user_data) +{ + const GDBusPropertyInfo *property; + + /* Strictly speaking, this function should also expect to receive + * method calls not on the org.freedesktop.DBus.Properties interface, + * but we don't do any during this testcase, so assert that. + */ + g_assert_cmpstr (interface_name, ==, "org.freedesktop.DBus.Properties"); + g_assert (g_dbus_method_invocation_get_method_info (invocation) == NULL); + + property = g_dbus_method_invocation_get_property_info (invocation); + + /* We should never be seeing any property calls on the com.example.Bar + * interface because it doesn't export any properties. + * + * In each case below make sure the interface is org.example.Foo. + */ + + /* Do a whole lot of asserts to make sure that invalid calls are still + * getting properly rejected by GDBusConnection and that our + * environment is as we expect it to be. + */ + if (g_str_equal (method_name, "Get")) + { + const gchar *iface_name, *prop_name; + + g_variant_get (parameters, "(&s&s)", &iface_name, &prop_name); + g_assert_cmpstr (iface_name, ==, "org.example.Foo"); + g_assert (property != NULL); + g_assert_cmpstr (prop_name, ==, property->name); + g_assert (property->flags & G_DBUS_PROPERTY_INFO_FLAGS_READABLE); + g_dbus_method_invocation_return_value (invocation, g_variant_new ("(v)", g_variant_new_string (prop_name))); + } + + else if (g_str_equal (method_name, "Set")) + { + const gchar *iface_name, *prop_name; + GVariant *value; + + g_variant_get (parameters, "(&s&sv)", &iface_name, &prop_name, &value); + g_assert_cmpstr (iface_name, ==, "org.example.Foo"); + g_assert (property != NULL); + g_assert_cmpstr (prop_name, ==, property->name); + g_assert (property->flags & G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE); + g_assert (g_variant_is_of_type (value, G_VARIANT_TYPE (property->signature))); + g_dbus_method_invocation_return_value (invocation, g_variant_new ("()")); + g_variant_unref (value); + } + + else if (g_str_equal (method_name, "GetAll")) + { + const gchar *iface_name; + + g_variant_get (parameters, "(&s)", &iface_name); + g_assert_cmpstr (iface_name, ==, "org.example.Foo"); + g_assert (property == NULL); + g_dbus_method_invocation_return_value (invocation, + g_variant_new_parsed ("({ 'PropertyUno': < 'uno' >," + " 'NotWritable': < 'notwrite' > },)")); + } + + else + g_assert_not_reached (); +} + +static gint outstanding_cases; + +static void +ensure_result_cb (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + GDBusConnection *connection = G_DBUS_CONNECTION (source); + GVariant *reply; + + reply = g_dbus_connection_call_finish (connection, result, NULL); + + if (user_data == NULL) + { + /* Expected an error */ + g_assert (reply == NULL); + } + else + { + /* Expected a reply of a particular format. */ + gchar *str; + + g_assert (reply != NULL); + str = g_variant_print (reply, TRUE); + g_assert_cmpstr (str, ==, (const gchar *) user_data); + g_free (str); + + g_variant_unref (reply); + } + + g_assert_cmpint (outstanding_cases, >, 0); + outstanding_cases--; +} + +static void +test_async_case (GDBusConnection *connection, + const gchar *expected_reply, + const gchar *method, + const gchar *format_string, + ...) +{ + va_list ap; + + va_start (ap, format_string); + + g_dbus_connection_call (connection, g_dbus_connection_get_unique_name (connection), "/foo", + "org.freedesktop.DBus.Properties", method, g_variant_new_va (format_string, NULL, &ap), + NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, ensure_result_cb, (gpointer) expected_reply); + + va_end (ap); + + outstanding_cases++; +} + +static void +test_async_properties (void) +{ + GError *error = NULL; + guint registration_id, registration_id2; + static const GDBusInterfaceVTable vtable = { + test_async_method_call, NULL, NULL + }; + + c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); + g_assert_no_error (error); + g_assert (c != NULL); + + registration_id = g_dbus_connection_register_object (c, + "/foo", + (GDBusInterfaceInfo *) &foo_interface_info, + &vtable, NULL, NULL, &error); + g_assert_no_error (error); + g_assert (registration_id); + registration_id2 = g_dbus_connection_register_object (c, + "/foo", + (GDBusInterfaceInfo *) &foo2_interface_info, + &vtable, NULL, NULL, &error); + g_assert_no_error (error); + g_assert (registration_id); + + test_async_case (c, NULL, "random", "()"); + + /* Test a variety of error cases */ + test_async_case (c, NULL, "Get", "(si)", "wrong signature", 5); + test_async_case (c, NULL, "Get", "(ss)", "org.example.WrongInterface", "zzz"); + test_async_case (c, NULL, "Get", "(ss)", "org.example.Foo", "NoSuchProperty"); + test_async_case (c, NULL, "Get", "(ss)", "org.example.Foo", "NotReadable"); + + test_async_case (c, NULL, "Set", "(si)", "wrong signature", 5); + test_async_case (c, NULL, "Set", "(ssv)", "org.example.WrongInterface", "zzz", g_variant_new_string ("")); + test_async_case (c, NULL, "Set", "(ssv)", "org.example.Foo", "NoSuchProperty", g_variant_new_string ("")); + test_async_case (c, NULL, "Set", "(ssv)", "org.example.Foo", "NotWritable", g_variant_new_string ("")); + test_async_case (c, NULL, "Set", "(ssv)", "org.example.Foo", "PropertyUno", g_variant_new_object_path ("/wrong")); + + test_async_case (c, NULL, "GetAll", "(si)", "wrong signature", 5); + test_async_case (c, NULL, "GetAll", "(s)", "org.example.WrongInterface"); + + /* Make sure that we get no unexpected async property calls for com.example.Foo2 */ + test_async_case (c, NULL, "Get", "(ss)", "org.example.Foo2", "zzz"); + test_async_case (c, NULL, "Set", "(ssv)", "org.example.Foo2", "zzz", g_variant_new_string ("")); + test_async_case (c, "(@a{sv} {},)", "GetAll", "(s)", "org.example.Foo2"); + + /* Now do the proper things */ + test_async_case (c, "(<'PropertyUno'>,)", "Get", "(ss)", "org.example.Foo", "PropertyUno"); + test_async_case (c, "(<'NotWritable'>,)", "Get", "(ss)", "org.example.Foo", "NotWritable"); + test_async_case (c, "()", "Set", "(ssv)", "org.example.Foo", "PropertyUno", g_variant_new_string ("")); + test_async_case (c, "()", "Set", "(ssv)", "org.example.Foo", "NotReadable", g_variant_new_string ("")); + test_async_case (c, "({'PropertyUno': <'uno'>, 'NotWritable': <'notwrite'>},)", "GetAll", "(s)", "org.example.Foo"); + + while (outstanding_cases) + g_main_context_iteration (NULL, TRUE); + + g_dbus_connection_unregister_object (c, registration_id); + g_dbus_connection_unregister_object (c, registration_id2); + g_object_unref (c); +} /* ---------------------------------------------------------------------------------------------------- */ @@ -1378,33 +1732,21 @@ main (int argc, { gint ret; - g_type_init (); g_test_init (&argc, &argv, NULL); /* all the tests rely on a shared main loop */ loop = g_main_loop_new (NULL, FALSE); - /* all the tests use a session bus with a well-known address that we can bring up and down - * using session_bus_up() and session_bus_down(). - */ - g_unsetenv ("DISPLAY"); - g_setenv ("DBUS_SESSION_BUS_ADDRESS", session_bus_get_temporary_address (), TRUE); - - session_bus_up (); - - /* TODO: wait a bit for the bus to come up.. ideally session_bus_up() won't return - * until one can connect to the bus but that's not how things work right now - */ - usleep (500 * 1000); - g_test_add_func ("/gdbus/object-registration", test_object_registration); + g_test_add_func ("/gdbus/registered-interfaces", test_registered_interfaces); + g_test_add_func ("/gdbus/async-properties", test_async_properties); + /* TODO: check that we spit out correct introspection data */ /* TODO: check that registering a whole subtree works */ - ret = g_test_run(); + ret = session_bus_run (); - /* tear down bus */ - session_bus_down (); + g_main_loop_unref (loop); return ret; }