diff --git a/gio/gdbusproxy.c b/gio/gdbusproxy.c index 6d84deced..9cfb82d70 100644 --- a/gio/gdbusproxy.c +++ b/gio/gdbusproxy.c @@ -59,8 +59,7 @@ * well-known name, the property cache is flushed when the name owner * vanishes and reloaded when a name owner appears. * - * If a #GDBusProxy is used for a well-known name, the owner of the - * name is tracked and can be read from + * The unique name owner of the proxy's name is tracked and can be read from * #GDBusProxy:g-name-owner. Connect to the #GObject::notify signal to * get notified of changes. Additionally, only signals and property * changes emitted from the current name owner are considered and @@ -1769,7 +1768,7 @@ async_initable_init_first (GAsyncInitable *initable) (GDestroyNotify) signal_subscription_unref); } - if (proxy->priv->name != NULL && !g_dbus_is_unique_name (proxy->priv->name)) + if (proxy->priv->name != NULL) { proxy->priv->name_owner_changed_subscription_id = g_dbus_connection_signal_subscribe (proxy->priv->connection, diff --git a/gio/tests/Makefile.am b/gio/tests/Makefile.am index b8a414954..8efb1eaa0 100644 --- a/gio/tests/Makefile.am +++ b/gio/tests/Makefile.am @@ -449,6 +449,7 @@ test_programs += \ gdbus-peer \ gdbus-proxy \ gdbus-proxy-threads \ + gdbus-proxy-unique-name \ gdbus-proxy-well-known-name \ gdbus-test-codegen \ gdbus-test-codegen-old \ @@ -483,6 +484,7 @@ gdbus_introspection_SOURCES = $(gdbus_sessionbus_sources) gdbus-int gdbus_names_SOURCES = $(gdbus_sessionbus_sources) gdbus-names.c gdbus_proxy_SOURCES = $(gdbus_sessionbus_sources) gdbus-proxy.c gdbus_proxy_threads_SOURCES = $(gdbus_sessionbus_sources) gdbus-proxy-threads.c +gdbus_proxy_unique_name_SOURCES = $(gdbus_sessionbus_sources) gdbus-proxy-unique-name.c gdbus_proxy_well_known_name_SOURCES = $(gdbus_sessionbus_sources) gdbus-proxy-well-known-name.c gdbus_test_codegen_SOURCES = $(gdbus_sessionbus_sources) gdbus-test-codegen.c nodist_gdbus_test_codegen_SOURCES = gdbus-test-codegen-generated.c gdbus-test-codegen-generated.h diff --git a/gio/tests/gdbus-proxy-unique-name.c b/gio/tests/gdbus-proxy-unique-name.c new file mode 100644 index 000000000..eacb0219c --- /dev/null +++ b/gio/tests/gdbus-proxy-unique-name.c @@ -0,0 +1,215 @@ +/* GLib testing framework examples and tests + * + * 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 + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * 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, see . + * + * Author: Cosimo Cecchi + */ + +#include +#include +#include + +#include "gdbus-tests.h" + +/* all tests rely on a shared mainloop */ +static GMainLoop *loop = NULL; + +/* ---------------------------------------------------------------------------------------------------- */ + +static void +proxy_new_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GDBusProxy **ret = user_data; + GError *error; + + error = NULL; + *ret = g_dbus_proxy_new_finish (res, &error); + g_assert_no_error (error); + g_assert_nonnull (ret); + + g_main_loop_quit (loop); +} + +static void +test_proxy_unique_name (void) +{ + GDBusProxy *wp; + GDBusProxy *p; + GDBusProxy *ap; + GDBusConnection *c; + GError *error; + gchar *name_owner; + gchar **property_names; + GVariant *variant; + GVariant *result; + char *unique_name; + + session_bus_up (); + + error = NULL; + c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); + g_assert_no_error (error); + g_assert_nonnull (c); + + /* use a proxy to the well-known name to set things up */ + wp = g_dbus_proxy_new_sync (c, + G_DBUS_PROXY_FLAGS_NONE, + NULL, /* GDBusInterfaceInfo* */ + "com.example.TestService", /* name */ + "/com/example/TestObject", /* object path */ + "com.example.Frob", /* interface name */ + NULL, /* GCancellable */ + &error); + g_assert_no_error (error); + + /* this is safe; testserver will exit once the bus goes away */ + g_assert_true (g_spawn_command_line_async (g_test_get_filename (G_TEST_BUILT, "gdbus-testserver", NULL), NULL)); + + /* check that we get the notify::g-name-owner signal */ + _g_assert_property_notify (wp, "g-name-owner"); + + /* now get the unique name of testserver's connection */ + unique_name = g_dbus_proxy_get_name_owner (wp); + + /* if we create another a proxy with the service being available, check that + * it has a name owner and properties + */ + error = NULL; + p = g_dbus_proxy_new_sync (c, + G_DBUS_PROXY_FLAGS_NONE, + NULL, /* GDBusInterfaceInfo* */ + unique_name, /* name */ + "/com/example/TestObject", /* object path */ + "com.example.Frob", /* interface name */ + NULL, /* GCancellable */ + &error); + g_assert_no_error (error); + name_owner = g_dbus_proxy_get_name_owner (p); + property_names = g_dbus_proxy_get_cached_property_names (p); + g_assert_true (g_dbus_is_unique_name (name_owner)); + g_assert_nonnull (property_names); + g_assert_cmpint (g_strv_length (property_names), >, 0); + g_free (name_owner); + g_strfreev (property_names); + + /* also for async: we should have a name owner and cached properties */ + g_dbus_proxy_new (c, + G_DBUS_PROXY_FLAGS_NONE, + NULL, /* GDBusInterfaceInfo* */ + unique_name, /* name */ + "/com/example/TestObject", /* object path */ + "com.example.Frob", /* interface name */ + NULL, /* GCancellable */ + (GAsyncReadyCallback) proxy_new_cb, + &ap); + g_main_loop_run (loop); + name_owner = g_dbus_proxy_get_name_owner (ap); + property_names = g_dbus_proxy_get_cached_property_names (ap); + g_assert_true (g_dbus_is_unique_name (name_owner)); + g_assert_nonnull (property_names); + g_assert_cmpint (g_strv_length (property_names), >, 0); + g_free (name_owner); + g_strfreev (property_names); + + /* Check property value is the initial value */ + variant = g_dbus_proxy_get_cached_property (p, "y"); + g_assert_nonnull (variant); + g_assert_cmpint (g_variant_get_byte (variant), ==, 1); + g_variant_unref (variant); + variant = g_dbus_proxy_get_cached_property (ap, "y"); + g_assert_nonnull (variant); + g_assert_cmpint (g_variant_get_byte (variant), ==, 1); + g_variant_unref (variant); + + /* Check that properties are updated on p */ + result = g_dbus_proxy_call_sync (p, + "FrobSetProperty", + g_variant_new ("(sv)", + "y", + g_variant_new_byte (42)), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + g_assert_no_error (error); + g_assert_nonnull (result); + g_assert_cmpstr (g_variant_get_type_string (result), ==, "()"); + g_variant_unref (result); + _g_assert_signal_received (p, "g-properties-changed"); + variant = g_dbus_proxy_get_cached_property (p, "y"); + g_assert_nonnull (variant); + g_assert_cmpint (g_variant_get_byte (variant), ==, 42); + g_variant_unref (variant); + variant = g_dbus_proxy_get_cached_property (ap, "y"); + g_assert_nonnull (variant); + g_assert_cmpint (g_variant_get_byte (variant), ==, 42); + g_variant_unref (variant); + + /* Nuke the service and check that we get the signal and then don't + * have a name owner nor any cached properties + */ + result = g_dbus_proxy_call_sync (p, + "Quit", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + g_assert_no_error (error); + g_assert_nonnull (result); + g_assert_cmpstr (g_variant_get_type_string (result), ==, "()"); + g_variant_unref (result); + /* and wait... */ + _g_assert_property_notify (p, "g-name-owner"); + /* now we shouldn't have a name owner nor any cached properties */ + g_assert_cmpstr (g_dbus_proxy_get_name_owner (p), ==, NULL); + g_assert_null (g_dbus_proxy_get_cached_property_names (p)); + g_assert_null (g_dbus_proxy_get_cached_property (p, "y")); + + g_object_unref (p); + g_object_unref (ap); + + g_object_unref (wp); + g_free (unique_name); + + g_object_unref (c); + + /* tear down bus */ + session_bus_down (); +} + +/* ---------------------------------------------------------------------------------------------------- */ + +int +main (int argc, + char *argv[]) +{ + gint ret; + + g_test_init (&argc, &argv, NULL); + + /* all the tests rely on a shared main loop */ + loop = g_main_loop_new (NULL, FALSE); + + g_test_dbus_unset (); + + g_test_add_func ("/gdbus/proxy-unique-name", test_proxy_unique_name); + + ret = g_test_run(); + return ret; +} diff --git a/gio/tests/meson.build b/gio/tests/meson.build index b71f61704..61c6be096 100644 --- a/gio/tests/meson.build +++ b/gio/tests/meson.build @@ -221,6 +221,7 @@ if host_machine.system() != 'windows' 'extra_sources' : extra_sources, 'dependencies' : [dbus1_dep], }, + 'gdbus-proxy-unique-name' : {'extra_sources' : extra_sources}, 'gdbus-proxy-well-known-name' : {'extra_sources' : extra_sources}, 'gdbus-test-codegen' : { 'extra_sources' : [extra_sources, gdbus_test_codegen_generated],