diff --git a/docs/reference/gio/migrating-gdbus.xml b/docs/reference/gio/migrating-gdbus.xml index 4f51679af..423ad16a4 100644 --- a/docs/reference/gio/migrating-gdbus.xml +++ b/docs/reference/gio/migrating-gdbus.xml @@ -60,6 +60,10 @@ linkend="gio-D-Bus-Introspection-Data">Introspection XML, dbus-glib doesn't. + + GTestDBus provides API to create isolated unit tests GDBus Test Scaffolding. + diff --git a/gio/gtestdbus.c b/gio/gtestdbus.c index 2315451a4..3ca064c17 100644 --- a/gio/gtestdbus.c +++ b/gio/gtestdbus.c @@ -318,6 +318,81 @@ _g_test_watcher_remove_pid (GPid pid) * * A helper class for testing code which uses D-Bus without touching the user's * session bus. + * + * + * Creating unit tests using GTestDBus + * + * Testing of D-Bus services can be tricky because normally we only ever run + * D-Bus services over an existing instance of the D-Bus daemon thus we + * usually don't activate D-Bus services that are not yet installed into the + * target system. The #GTestDBus object makes this easier for us by taking care + * of the lower level tasks such as running a private D-Bus daemon and looking + * up uninstalled services in customizable locations, typically in your source code tree. + * + * + * The first thing you will need is a separate service description file for the + * D-Bus daemon. Typically a 'services' subdirectory of your 'tests' directory + * is a good place to put this file. + * + * + * The service file should list your service along with an absolute path to the + * uninstalled service executable in your source tree. Using autotools we would + * achieve this by adding a file such as 'my-server.service.in' in the services + * directory and have it processed by configure. + * + * [D-BUS Service] + * Name=org.gtk.GDBus.Examples.ObjectManager + * Exec=@abs_top_builddir@/gio/tests/gdbus-example-objectmanager-server + * + * You will also need to indicate this service directory in your test + * fixtures, so you will need to pass the path while compiling your + * test cases. Typically this is done with autotools with an added + * preprocessor flag specified to compile your tests such as: + * + * -DTEST_SERVICES=\""$(abs_top_builddir)/tests/services"\" + * + * + * + * Once you have a service definition file which is local to your source tree, + * you can proceed to setup a GTest fixture using the GTestDBus scaffolding. + * + * Test Fixture for D-Bus services + * + * + * FIXME: MISSING XINCLUDE CONTENT + * + * + * + * + * + * Note that these examples only deal with isolating the D-Bus aspect of your + * service. To successfully run isolated unit tests on your service you may need + * some additional modifications to your test case fixture. For example; if your + * service uses GSettings and installs a schema then it is important that your test service + * not load the schema in the ordinary installed location (chances are that your service + * and schema files are not yet installed, or worse; there is an older version of the + * schema file sitting in the install location). + * + * + * Most of the time we can work around these obstacles using the environment. Since the + * environment is inherited by the D-Bus daemon created by GTestDBus and then in turn + * inherited by any services the D-Bus daemon activates, using the setup routine for your + * fixture is a practical place to help sandbox your runtime environment. For the rather + * typical GSettings case we can work around this by setting GSETTINGS_SCHEMA_DIR to the + * in tree directory holding your schemas in the above fixture_setup() routine. + * + * + * The GSettings schemas need to be locally pre-compiled for this to work. This can be achieved + * by compiling the schemas locally as a step before running test cases, an autotools setup might + * do the following in the directory holding schemas: + * + * all-am: + * $(GLIB_COMPILE_SCHEMAS) . + * + * CLEANFILES += gschemas.compiled + * + * + * */ typedef struct _GTestDBusClass GTestDBusClass; diff --git a/gio/tests/gdbus-test-fixture.c b/gio/tests/gdbus-test-fixture.c index ef1f6c56b..a4403dd72 100644 --- a/gio/tests/gdbus-test-fixture.c +++ b/gio/tests/gdbus-test-fixture.c @@ -1,26 +1,11 @@ -/* gdbus-test-fixture.c - Test covering activation of in-tree servers. - * - * Copyright (C) 2012 Intel Corporation - * - * This program 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 License, or (at your option) version 3. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * Authors: Tristan Van Berkom - */ -#include #include "gdbus-example-objectmanager-generated.h" +/* ---------------------------------------------------------------------------------------------------- */ + +/* The fixture contains a GTestDBus object and + * a proxy to the service we're going to be testing. + */ typedef struct { GTestDBus *dbus; GDBusObjectManager *manager; @@ -29,49 +14,24 @@ typedef struct { static void fixture_setup (TestFixture *fixture, gconstpointer unused) { - /* Create the global dbus-daemon for this test suite */ - fixture->dbus = g_test_dbus_new (G_TEST_DBUS_NONE); - - /* Add the private directory with our in-tree service files */ - g_test_dbus_add_service_dir (fixture->dbus, TEST_SERVICES); - - /* Start the private D-Bus daemon */ - g_test_dbus_up (fixture->dbus); -} - -static void -fixture_teardown (TestFixture *fixture, gconstpointer unused) -{ - if (fixture->manager) - g_object_unref (fixture->manager); - - /* Stop the private D-Bus daemon */ - g_test_dbus_down (fixture->dbus); - - g_object_unref (fixture->dbus); -} - -/* The gdbus-example-objectmanager-server exports 10 objects, - * to test the server has actually activated, let's ensure - * that 10 objects exist. - */ -static void -assert_ten_objects (GDBusObjectManager *manager) -{ - GList *objects; - - objects = g_dbus_object_manager_get_objects (manager); - - g_assert_cmpint (g_list_length (objects), ==, 10); - g_list_free_full (objects, g_object_unref); -} - -static void -test_gtest_dbus (TestFixture *fixture, gconstpointer unused) -{ - GError *error = NULL; + /* Create the global dbus-daemon for this test suite + */ + fixture->dbus = g_test_dbus_new (G_TEST_DBUS_NONE); + + /* Add the private directory with our in-tree service files, + * TEST_SERVICES is defined by the build system to point + * to the right directory. + */ + g_test_dbus_add_service_dir (fixture->dbus, TEST_SERVICES); + + /* Start the private D-Bus daemon + */ + g_test_dbus_up (fixture->dbus); + + /* Create the proxy that we're going to test + */ fixture->manager = example_object_manager_client_new_for_bus_sync (G_BUS_TYPE_SESSION, G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE, @@ -81,21 +41,45 @@ test_gtest_dbus (TestFixture *fixture, gconstpointer unused) &error); if (fixture->manager == NULL) g_error ("Error getting object manager client: %s", error->message); +} - assert_ten_objects (fixture->manager); +static void +fixture_teardown (TestFixture *fixture, gconstpointer unused) +{ + /* Tear down the proxy + */ + if (fixture->manager) + g_object_unref (fixture->manager); + + /* Stop the private D-Bus daemon + */ + g_test_dbus_down (fixture->dbus); + g_object_unref (fixture->dbus); +} + +/* The gdbus-example-objectmanager-server exports 10 objects, + * to test the server has actually activated, let's ensure + * that 10 objects exist. + */ +static void +test_gtest_dbus (TestFixture *fixture, gconstpointer unused) +{ + GList *objects; + + objects = g_dbus_object_manager_get_objects (fixture->manager); + + g_assert_cmpint (g_list_length (objects), ==, 10); + g_list_free_full (objects, g_object_unref); } int main (int argc, char *argv[]) { -#if !GLIB_CHECK_VERSION (2, 35, 1) - g_type_init (); -#endif g_test_init (&argc, &argv, NULL); - /* Ensure that we can bring the GTestDBus up and down a hand full of times - * in a row, each time successfully activating the in-tree service + /* This test simply ensures that we can bring the GTestDBus up and down a hand + * full of times in a row, each time successfully activating the in-tree service */ g_test_add ("/GTestDBus/Cycle1", TestFixture, NULL, fixture_setup, test_gtest_dbus, fixture_teardown);