1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 /* e-test-server-utils.c - Test scaffolding to run tests with in-tree data server.
5 * Copyright (C) 2012 Intel Corporation
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) version 3.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with the program; if not, see <http://www.gnu.org/licenses/>
20 * Authors: Tristan Van Berkom <tristanvb@openismus.com>
23 #include "e-test-server-utils.h"
25 #define ADDRESS_BOOK_SOURCE_UID "test-address-book"
26 #define CALENDAR_SOURCE_UID "test-calendar"
28 /* FIXME, currently we are unable to achieve server activation
29 * twice in a single test case, so we're using one D-Bus server
30 * throughout an entire test suite.
32 * When this is fixed we can migrate the D-Bus initialization
33 * and teardown from e_test_server_utils_run() to
34 * e_test_server_utils_setup() and e_test_server_utils_teardown()
35 * and this will transparantly change the way tests run using
36 * this test framework.
38 #define GLOBAL_DBUS_DAEMON 1
40 #if GLOBAL_DBUS_DAEMON
41 static GTestDBus *global_test_dbus = NULL;
45 ETestServerFixture *fixture;
46 ETestServerClosure *closure;
50 setup_environment (void)
52 g_assert (g_setenv ("XDG_DATA_HOME", EDS_TEST_WORK_DIR, TRUE));
53 g_assert (g_setenv ("XDG_CACHE_HOME", EDS_TEST_WORK_DIR, TRUE));
54 g_assert (g_setenv ("XDG_CONFIG_HOME", EDS_TEST_WORK_DIR, TRUE));
55 g_assert (g_setenv ("GSETTINGS_SCHEMA_DIR", EDS_TEST_SCHEMA_DIR, TRUE));
56 g_assert (g_setenv ("EDS_CALENDAR_MODULES", EDS_TEST_CALENDAR_DIR, TRUE));
57 g_assert (g_setenv ("EDS_ADDRESS_BOOK_MODULES", EDS_TEST_ADDRESS_BOOK_DIR, TRUE));
61 delete_work_directory (void)
63 /* XXX Instead of complex error checking here, we should ideally use
64 * a recursive GDir / g_unlink() function.
66 * We cannot use GFile and the recursive delete function without
67 * corrupting our contained D-Bus environment with service files
70 const gchar *argv[] = { "/bin/rm", "-rf", EDS_TEST_WORK_DIR, NULL };
71 gboolean spawn_succeeded;
74 spawn_succeeded = g_spawn_sync (
75 NULL, (gchar **) argv, NULL, 0, NULL, NULL,
76 NULL, NULL, &exit_status, NULL);
78 g_assert (spawn_succeeded);
79 g_assert (WIFEXITED (exit_status));
80 g_assert_cmpint (WEXITSTATUS (exit_status), ==, 0);
84 e_test_server_utils_bootstrap_timeout (FixturePair *pair)
86 g_error ("Timed out while waiting for ESource creation from the registry");
91 e_test_server_utils_source_added (ESourceRegistry *registry,
97 switch (pair->closure->type) {
98 case E_TEST_SERVER_ADDRESS_BOOK:
99 if (g_strcmp0 (e_source_get_uid (source), ADDRESS_BOOK_SOURCE_UID) != 0)
102 pair->fixture->service.book_client = e_book_client_new (source, &error);
103 if (!pair->fixture->service.book_client)
104 g_error ("Unable to create the test book: %s", error->message);
106 if (!e_client_open_sync (E_CLIENT (pair->fixture->service.book_client), FALSE, NULL, &error))
107 g_error ("Unable to open book client: %s", error->message);
111 case E_TEST_SERVER_DEPRECATED_ADDRESS_BOOK:
112 if (g_strcmp0 (e_source_get_uid (source), ADDRESS_BOOK_SOURCE_UID) != 0)
115 pair->fixture->service.book = e_book_new (source, &error);
116 if (!pair->fixture->service.book)
117 g_error ("Unable to create the test book: %s", error->message);
119 if (!e_book_open (pair->fixture->service.book, FALSE, &error))
120 g_error ("Unable to open book: %s", error->message);
124 case E_TEST_SERVER_CALENDAR:
125 if (g_strcmp0 (e_source_get_uid (source), CALENDAR_SOURCE_UID) != 0)
128 pair->fixture->service.calendar_client = e_cal_client_new (source,
129 pair->closure->calendar_source_type,
131 if (!pair->fixture->service.calendar_client)
132 g_error ("Unable to create the test calendar: %s", error->message);
134 if (!e_client_open_sync (E_CLIENT (pair->fixture->service.calendar_client), FALSE, NULL, &error))
135 g_error ("Unable to open calendar client: %s", error->message);
139 case E_TEST_SERVER_DEPRECATED_CALENDAR:
140 if (g_strcmp0 (e_source_get_uid (source), CALENDAR_SOURCE_UID) != 0)
143 pair->fixture->service.calendar = e_cal_new (source, pair->closure->calendar_source_type);
144 if (!pair->fixture->service.calendar)
145 g_error ("Unable to create the test calendar");
147 if (!e_cal_open (pair->fixture->service.calendar, FALSE, &error))
148 g_error ("Unable to open calendar: %s", error->message);
152 case E_TEST_SERVER_NONE:
156 g_main_loop_quit (pair->fixture->loop);
160 e_test_server_utils_bootstrap_idle (FixturePair *pair)
162 ESourceBackend *backend = NULL;
163 ESource *scratch = NULL;
164 GError *error = NULL;
166 pair->fixture->registry = e_source_registry_new_sync (NULL, &error);
168 if (!pair->fixture->registry)
169 g_error ("Unable to create the test registry: %s", error->message);
171 g_signal_connect (pair->fixture->registry, "source-added",
172 G_CALLBACK (e_test_server_utils_source_added), pair);
174 /* Create an address book */
175 switch (pair->closure->type) {
176 case E_TEST_SERVER_ADDRESS_BOOK:
177 case E_TEST_SERVER_DEPRECATED_ADDRESS_BOOK:
179 scratch = e_source_new_with_uid (ADDRESS_BOOK_SOURCE_UID, NULL, &error);
181 g_error ("Failed to create scratch source for an addressbook: %s", error->message);
183 /* Ensure Book type */
184 backend = e_source_get_extension (scratch, E_SOURCE_EXTENSION_ADDRESS_BOOK);
185 e_source_backend_set_backend_name (backend, "local");
188 case E_TEST_SERVER_CALENDAR:
189 case E_TEST_SERVER_DEPRECATED_CALENDAR:
191 scratch = e_source_new_with_uid (CALENDAR_SOURCE_UID, NULL, &error);
193 g_error ("Failed to create scratch source for a calendar: %s", error->message);
195 /* Ensure Calendar type source (how to specify the backend here ?? */
196 backend = e_source_get_extension (scratch, E_SOURCE_EXTENSION_CALENDAR);
197 e_source_backend_set_backend_name (backend, "local");
201 case E_TEST_SERVER_NONE:
206 if (pair->closure->customize)
207 pair->closure->customize (scratch, pair->closure);
209 if (!e_source_registry_commit_source_sync (pair->fixture->registry, scratch, NULL, &error))
210 g_error ("Unable to add new addressbook source to the registry: %s", error->message);
212 g_object_unref (scratch);
215 if (pair->closure->type != E_TEST_SERVER_NONE)
216 g_timeout_add (20 * 1000, (GSourceFunc) e_test_server_utils_bootstrap_timeout, pair);
218 g_main_loop_quit (pair->fixture->loop);
224 * e_test_server_utils_setup:
225 * @fixture: A #ETestServerFixture
226 * @user_data: A #ETestServerClosure or derived structure provided by the test.
228 * A setup function for the #ETestServerFixture fixture
231 e_test_server_utils_setup (ETestServerFixture *fixture,
232 gconstpointer user_data)
234 ETestServerClosure *closure = (ETestServerClosure *) user_data;
235 FixturePair pair = { fixture, closure };
237 /* Create work directory */
238 g_assert (g_mkdir_with_parents (EDS_TEST_WORK_DIR, 0755) == 0);
240 fixture->loop = g_main_loop_new (NULL, FALSE);
242 #if !GLOBAL_DBUS_DAEMON
243 /* Create the global dbus-daemon for this test suite */
244 fixture->dbus = g_test_dbus_new (G_TEST_DBUS_NONE);
246 /* Add the private directory with our in-tree service files */
247 g_test_dbus_add_service_dir (fixture->dbus, EDS_TEST_DBUS_SERVICE_DIR);
249 /* Start the private D-Bus daemon */
250 g_test_dbus_up (fixture->dbus);
252 fixture->dbus = global_test_dbus;
255 g_idle_add ((GSourceFunc) e_test_server_utils_bootstrap_idle, &pair);
256 g_main_loop_run (fixture->loop);
257 g_signal_handlers_disconnect_by_func (fixture->registry, e_test_server_utils_source_added, &pair);
261 * e_test_server_utils_teardown:
262 * @fixture: A #ETestServerFixture
263 * @user_data: A #ETestServerClosure or derived structure provided by the test.
265 * A teardown function for the #ETestServerFixture fixture
268 e_test_server_utils_teardown (ETestServerFixture *fixture,
269 gconstpointer user_data)
271 ETestServerClosure *closure = (ETestServerClosure *) user_data;
272 GError *error = NULL;
274 switch (closure->type) {
275 case E_TEST_SERVER_ADDRESS_BOOK:
276 if (!e_client_remove_sync (E_CLIENT (fixture->service.book_client), NULL, &error)) {
277 g_message ("Failed to remove test book: %s (ignoring)", error->message);
278 g_clear_error (&error);
280 g_object_unref (fixture->service.book_client);
281 fixture->service.book_client = NULL;
284 case E_TEST_SERVER_DEPRECATED_ADDRESS_BOOK:
285 if (!e_book_remove (fixture->service.book, &error)) {
286 g_message ("Failed to remove test book: %s (ignoring)", error->message);
287 g_clear_error (&error);
289 g_object_unref (fixture->service.book);
290 fixture->service.book = NULL;
293 case E_TEST_SERVER_CALENDAR:
294 if (!e_client_remove_sync (E_CLIENT (fixture->service.calendar_client), NULL, &error)) {
295 g_message ("Failed to remove test calendar: %s (ignoring)", error->message);
296 g_clear_error (&error);
298 g_object_unref (fixture->service.calendar_client);
299 fixture->service.calendar_client = NULL;
302 case E_TEST_SERVER_DEPRECATED_CALENDAR:
303 if (!e_cal_remove (fixture->service.calendar, &error)) {
304 g_message ("Failed to remove test calendar: %s (ignoring)", error->message);
305 g_clear_error (&error);
307 g_object_unref (fixture->service.calendar);
308 fixture->service.calendar = NULL;
310 case E_TEST_SERVER_NONE:
314 g_object_run_dispose (G_OBJECT (fixture->registry));
315 g_object_unref (fixture->registry);
316 fixture->registry = NULL;
318 g_main_loop_unref (fixture->loop);
319 fixture->loop = NULL;
321 #if !GLOBAL_DBUS_DAEMON
322 /* Teardown the D-Bus Daemon
324 * Note that we intentionally leak the TestDBus daemon
325 * in this case, presumably this is due to some leaked
326 * GDBusConnection reference counting
328 g_test_dbus_down (fixture->dbus);
329 g_object_unref (fixture->dbus);
330 fixture->dbus = NULL;
332 fixture->dbus = NULL;
335 /* Cleanup work directory */
336 if (!closure->keep_work_directory)
337 delete_work_directory ();
341 e_test_server_utils_run (void)
345 /* Cleanup work directory */
346 delete_work_directory ();
348 setup_environment ();
350 #if GLOBAL_DBUS_DAEMON
352 /* Create the global dbus-daemon for this test suite */
353 global_test_dbus = g_test_dbus_new (G_TEST_DBUS_NONE);
355 /* Add the private directory with our in-tree service files */
356 g_test_dbus_add_service_dir (global_test_dbus, EDS_TEST_DBUS_SERVICE_DIR);
358 /* Start the private D-Bus daemon */
359 g_test_dbus_up (global_test_dbus);
362 /* Run the GTest suite */
363 tests_ret = g_test_run ();
365 #if GLOBAL_DBUS_DAEMON
366 /* Teardown the D-Bus Daemon
368 * Note that we intentionally leak the TestDBus daemon
369 * in this case, presumably this is due to some leaked
370 * GDBusConnection reference counting
372 g_test_dbus_stop (global_test_dbus);
373 /* g_object_unref (global_test_dbus); */
374 global_test_dbus = NULL;