From d890b1ce5f92afa7b86b229bfbc48c4207ec3a54 Mon Sep 17 00:00:00 2001 From: Frederic Martinsons Date: Sat, 16 Jan 2021 08:03:34 +0100 Subject: [PATCH] Extend dbus watching name tests: - use watcher auto start flag. - use watch_name_on_connection_with_closures. - use an existing service name for auto start. Closes #2011 Signed-off-by: Frederic Martinsons --- gio/tests/fake-service-name.c | 119 ++++++++ gio/tests/gdbus-names.c | 259 ++++++++++++++---- gio/tests/meson.build | 1 + gio/tests/services/meson.build | 1 + .../org.gtk.GDBus.FakeService.service.in | 3 + 5 files changed, 328 insertions(+), 55 deletions(-) create mode 100644 gio/tests/fake-service-name.c create mode 100644 gio/tests/services/org.gtk.GDBus.FakeService.service.in diff --git a/gio/tests/fake-service-name.c b/gio/tests/fake-service-name.c new file mode 100644 index 000000000..1a601a50c --- /dev/null +++ b/gio/tests/fake-service-name.c @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2021 Frederic Martinsons + * + * 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 . + * + * Authors: Frederic Martinsons + */ + +/* A dummy service which just own a dbus name and implement a method to quit*/ + +#include +#include + +static GDBusNodeInfo *introspection_data = NULL; +static GMainLoop *loop = NULL; +static const gchar introspection_xml[] = + "" + " " + " " + " " + ""; + +static void +incoming_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) +{ + if (g_strcmp0 (method_name, "Quit") == 0) + { + g_dbus_method_invocation_return_value (invocation, NULL); + g_main_loop_quit (loop); + } +} + +static const GDBusInterfaceVTable interface_vtable = { + incoming_method_call, + NULL, + NULL +}; + +static void +on_bus_acquired (GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + guint registration_id; + GError *error = NULL; + g_test_message ("Acquired a message bus connection"); + + registration_id = g_dbus_connection_register_object (connection, + "/org/gtk/GDBus/FakeService", + introspection_data->interfaces[0], + &interface_vtable, + NULL, /* user_data */ + NULL, /* user_data_free_func */ + &error); + g_assert_no_error (error); + g_assert (registration_id > 0); +} + +static void +on_name_acquired (GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + g_test_message ("Acquired the name %s", name); +} + +static void +on_name_lost (GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + g_test_message ("Lost the name %s", name); +} + +gint +main (gint argc, gchar *argv[]) +{ + guint id; + + loop = g_main_loop_new (NULL, FALSE); + introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL); + g_assert (introspection_data != NULL); + + id = g_bus_own_name (G_BUS_TYPE_SESSION, + "org.gtk.GDBus.FakeService", + G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT | + G_BUS_NAME_OWNER_FLAGS_REPLACE, + on_bus_acquired, + on_name_acquired, + on_name_lost, + loop, + NULL); + + g_main_loop_run (loop); + + g_bus_unown_name (id); + g_main_loop_unref (loop); + g_dbus_node_info_unref (introspection_data); + + return 0; +} diff --git a/gio/tests/gdbus-names.c b/gio/tests/gdbus-names.c index c1d925342..05d2015d0 100644 --- a/gio/tests/gdbus-names.c +++ b/gio/tests/gdbus-names.c @@ -32,7 +32,6 @@ static GMainLoop *loop; typedef struct { - GMainLoop *loop; gboolean expect_null_connection; guint num_bus_acquired; guint num_acquired; @@ -537,6 +536,7 @@ name_appeared_handler (GDBusConnection *connection, gpointer user_data) { WatchNameData *data = user_data; + if (data->expect_null_connection) { g_assert (connection == NULL); @@ -556,6 +556,7 @@ name_vanished_handler (GDBusConnection *connection, gpointer user_data) { WatchNameData *data = user_data; + if (data->expect_null_connection) { g_assert (connection == NULL); @@ -569,13 +570,95 @@ name_vanished_handler (GDBusConnection *connection, g_main_loop_quit (loop); } +typedef struct +{ + guint watcher_flags; + gboolean watch_with_closures; + gboolean existing_service; +} WatchNameTest; + +static const WatchNameTest watch_no_closures_no_flags = { + .watcher_flags = G_BUS_NAME_WATCHER_FLAGS_NONE, + .watch_with_closures = FALSE, + .existing_service = FALSE +}; + +static const WatchNameTest watch_no_closures_flags_auto_start = { + .watcher_flags = G_BUS_NAME_WATCHER_FLAGS_AUTO_START, + .watch_with_closures = FALSE, + .existing_service = FALSE +}; + +static const WatchNameTest watch_no_closures_flags_auto_start_service_exist = { + .watcher_flags = G_BUS_NAME_WATCHER_FLAGS_AUTO_START, + .watch_with_closures = FALSE, + .existing_service = TRUE +}; + +static const WatchNameTest watch_closures_no_flags = { + .watcher_flags = G_BUS_NAME_WATCHER_FLAGS_NONE, + .watch_with_closures = TRUE, + .existing_service = FALSE +}; + +static const WatchNameTest watch_closures_flags_auto_start = { + .watcher_flags = G_BUS_NAME_WATCHER_FLAGS_AUTO_START, + .watch_with_closures = TRUE, + .existing_service = FALSE +}; + static void -test_bus_watch_name (void) +stop_service (GDBusConnection *connection, + WatchNameData *data) +{ + GError *error = NULL; + GDBusProxy *proxy = NULL; + + data->num_vanished = 0; + + proxy = g_dbus_proxy_new_sync (connection, + G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, + NULL, + "org.gtk.GDBus.FakeService", + "/org/gtk/GDBus/FakeService", + "org.gtk.GDBus.FakeService", + NULL, + &error); + g_assert_no_error (error); + + g_dbus_proxy_call_sync (proxy, + "Quit", + NULL, + G_DBUS_CALL_FLAGS_NO_AUTO_START, + 100, + NULL, + &error); + g_assert_no_error (error); + g_object_unref (proxy); + while (data->num_vanished == 0) + g_main_loop_run (loop); +} + +static void +test_bus_watch_name (gconstpointer d) { WatchNameData data; guint id; guint owner_id; GDBusConnection *connection; + const WatchNameTest *watch_name_test; + const gchar *name; + + watch_name_test = (WatchNameTest *) d; + + if (watch_name_test->existing_service) + { + name = "org.gtk.GDBus.FakeService"; + } + else + { + name = "org.gtk.GDBus.Name1"; + } /* * First check that name_vanished_handler() is invoked if there is no bus. @@ -587,8 +670,8 @@ test_bus_watch_name (void) data.num_vanished = 0; data.expect_null_connection = TRUE; id = g_bus_watch_name (G_BUS_TYPE_SESSION, - "org.gtk.GDBus.Name1", - G_BUS_NAME_WATCHER_FLAGS_NONE, + name, + watch_name_test->watcher_flags, name_appeared_handler, name_vanished_handler, &data, @@ -613,7 +696,7 @@ test_bus_watch_name (void) data.num_lost = 0; data.expect_null_connection = FALSE; owner_id = g_bus_own_name (G_BUS_TYPE_SESSION, - "org.gtk.GDBus.Name1", + name, G_BUS_NAME_OWNER_FLAGS_NONE, w_bus_acquired_handler, w_name_acquired_handler, @@ -622,7 +705,7 @@ test_bus_watch_name (void) (GDestroyNotify) watch_name_data_free_func); g_main_loop_run (loop); g_assert_cmpint (data.num_acquired, ==, 1); - g_assert_cmpint (data.num_lost, ==, 0); + g_assert_cmpint (data.num_lost, ==, 0); connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL); g_assert (connection != NULL); @@ -630,13 +713,28 @@ test_bus_watch_name (void) /* now watch the name */ data.num_appeared = 0; data.num_vanished = 0; - id = g_bus_watch_name_on_connection (connection, - "org.gtk.GDBus.Name1", - G_BUS_NAME_WATCHER_FLAGS_NONE, - name_appeared_handler, - name_vanished_handler, - &data, - (GDestroyNotify) watch_name_data_free_func); + if (watch_name_test->watch_with_closures) + { + id = g_bus_watch_name_on_connection_with_closures (connection, + name, + watch_name_test->watcher_flags, + g_cclosure_new (G_CALLBACK (name_appeared_handler), + &data, + NULL), + g_cclosure_new (G_CALLBACK (name_vanished_handler), + &data, + (GClosureNotify) watch_name_data_free_func)); + } + else + { + id = g_bus_watch_name_on_connection (connection, + name, + watch_name_test->watcher_flags, + name_appeared_handler, + name_vanished_handler, + &data, + (GDestroyNotify) watch_name_data_free_func); + } g_assert_cmpint (data.num_appeared, ==, 0); g_assert_cmpint (data.num_vanished, ==, 0); g_main_loop_run (loop); @@ -649,8 +747,6 @@ test_bus_watch_name (void) g_bus_unwatch_name (id); g_assert_cmpint (data.num_free_func, ==, 1); - g_object_unref (connection); - /* unown the name */ g_bus_unown_name (owner_id); g_main_loop_run (loop); @@ -666,56 +762,96 @@ test_bus_watch_name (void) data.num_appeared = 0; data.num_vanished = 0; data.num_free_func = 0; - id = g_bus_watch_name_with_closures (G_BUS_TYPE_SESSION, - "org.gtk.GDBus.Name1", - G_BUS_NAME_WATCHER_FLAGS_NONE, - g_cclosure_new (G_CALLBACK (name_appeared_handler), - &data, - NULL), - g_cclosure_new (G_CALLBACK (name_vanished_handler), - &data, - (GClosureNotify) watch_name_data_free_func)); + if (watch_name_test->watch_with_closures) + { + id = g_bus_watch_name_with_closures (G_BUS_TYPE_SESSION, + name, + watch_name_test->watcher_flags, + g_cclosure_new (G_CALLBACK (name_appeared_handler), + &data, + NULL), + g_cclosure_new (G_CALLBACK (name_vanished_handler), + &data, + (GClosureNotify) watch_name_data_free_func)); + } + else + { + id = g_bus_watch_name (G_BUS_TYPE_SESSION, + name, + watch_name_test->watcher_flags, + name_appeared_handler, + name_vanished_handler, + &data, + (GDestroyNotify) watch_name_data_free_func); + } + g_assert_cmpint (data.num_appeared, ==, 0); g_assert_cmpint (data.num_vanished, ==, 0); g_main_loop_run (loop); - g_assert_cmpint (data.num_appeared, ==, 0); - g_assert_cmpint (data.num_vanished, ==, 1); + if (watch_name_test->existing_service) + { + g_assert_cmpint (data.num_appeared, ==, 1); + g_assert_cmpint (data.num_vanished, ==, 0); + } + else + { + g_assert_cmpint (data.num_appeared, ==, 0); + g_assert_cmpint (data.num_vanished, ==, 1); + } - /* own the name */ - data.num_acquired = 0; - data.num_lost = 0; - data.expect_null_connection = FALSE; - owner_id = g_bus_own_name (G_BUS_TYPE_SESSION, - "org.gtk.GDBus.Name1", - G_BUS_NAME_OWNER_FLAGS_NONE, - w_bus_acquired_handler, - w_name_acquired_handler, - w_name_lost_handler, - &data, - (GDestroyNotify) watch_name_data_free_func); - while (data.num_acquired == 0 || data.num_appeared == 0) - g_main_loop_run (loop); - g_assert_cmpint (data.num_acquired, ==, 1); - g_assert_cmpint (data.num_lost, ==, 0); - g_assert_cmpint (data.num_appeared, ==, 1); - g_assert_cmpint (data.num_vanished, ==, 1); + if (!watch_name_test->existing_service) + { + /* own the name */ + data.num_acquired = 0; + data.num_lost = 0; + data.expect_null_connection = FALSE; + owner_id = g_bus_own_name (G_BUS_TYPE_SESSION, + name, + G_BUS_NAME_OWNER_FLAGS_NONE, + w_bus_acquired_handler, + w_name_acquired_handler, + w_name_lost_handler, + &data, + (GDestroyNotify) watch_name_data_free_func); + while (data.num_acquired == 0 || data.num_appeared == 0) + g_main_loop_run (loop); + g_assert_cmpint (data.num_acquired, ==, 1); + g_assert_cmpint (data.num_lost, ==, 0); + g_assert_cmpint (data.num_appeared, ==, 1); + g_assert_cmpint (data.num_vanished, ==, 1); + } + data.expect_null_connection = TRUE; + if (watch_name_test->existing_service) + { + data.expect_null_connection = FALSE; + stop_service (connection, &data); + } + g_object_unref (connection); /* * Nuke the bus and check that the name vanishes and is lost. */ - data.expect_null_connection = TRUE; session_bus_stop (); - g_main_loop_run (loop); - g_assert_cmpint (data.num_lost, ==, 1); - g_assert_cmpint (data.num_vanished, ==, 2); - + if (!watch_name_test->existing_service) + { + g_main_loop_run (loop); + g_assert_cmpint (data.num_lost, ==, 1); + g_assert_cmpint (data.num_vanished, ==, 2); + } + else + { + g_assert_cmpint (data.num_lost, ==, 0); + g_assert_cmpint (data.num_vanished, ==, 1); + } g_bus_unwatch_name (id); g_assert_cmpint (data.num_free_func, ==, 1); - g_bus_unown_name (owner_id); - g_main_loop_run (loop); - g_assert_cmpint (data.num_free_func, ==, 2); - + if (!watch_name_test->existing_service) + { + g_bus_unown_name (owner_id); + g_main_loop_run (loop); + g_assert_cmpint (data.num_free_func, ==, 2); + } session_bus_down (); } @@ -828,9 +964,22 @@ main (int argc, g_test_add_func ("/gdbus/validate-names", test_validate_names); g_test_add_func ("/gdbus/bus-own-name", test_bus_own_name); - g_test_add_func ("/gdbus/bus-watch-name", test_bus_watch_name); + g_test_add_data_func ("/gdbus/bus-watch-name", + &watch_no_closures_no_flags, + test_bus_watch_name); + g_test_add_data_func ("/gdbus/bus-watch-name-auto-start", + &watch_no_closures_flags_auto_start, + test_bus_watch_name); + g_test_add_data_func ("/gdbus/bus-watch-name-auto-start-service-exist", + &watch_no_closures_flags_auto_start_service_exist, + test_bus_watch_name); + g_test_add_data_func ("/gdbus/bus-watch-name-closures", + &watch_closures_no_flags, + test_bus_watch_name); + g_test_add_data_func ("/gdbus/bus-watch-name-closures-auto-start", + &watch_closures_flags_auto_start, + test_bus_watch_name); g_test_add_func ("/gdbus/escape-object-path", test_escape_object_path); - ret = g_test_run(); g_main_loop_unref (loop); diff --git a/gio/tests/meson.build b/gio/tests/meson.build index d8ebd56ac..aaa54afae 100644 --- a/gio/tests/meson.build +++ b/gio/tests/meson.build @@ -350,6 +350,7 @@ if host_machine.system() != 'windows' 'fake-document-portal' : { 'extra_sources': fake_document_portal_generated, }, + 'fake-service-name' : {} } endif # have_dbus_daemon diff --git a/gio/tests/services/meson.build b/gio/tests/services/meson.build index 059eeb667..fd5117e23 100644 --- a/gio/tests/services/meson.build +++ b/gio/tests/services/meson.build @@ -1,5 +1,6 @@ dbus_service_files = [ 'org.freedesktop.portal.Documents.service', + 'org.gtk.GDBus.FakeService.service' ] srcdir_cdata = configuration_data() diff --git a/gio/tests/services/org.gtk.GDBus.FakeService.service.in b/gio/tests/services/org.gtk.GDBus.FakeService.service.in new file mode 100644 index 000000000..bbfcd73eb --- /dev/null +++ b/gio/tests/services/org.gtk.GDBus.FakeService.service.in @@ -0,0 +1,3 @@ +[D-BUS Service] +Name=org.gtk.GDBus.FakeService +Exec=@installed_tests_dir@/fake-service-name