diff --git a/library/tests/Makefile.am b/library/tests/Makefile.am index 2cd4221..9d2146c 100644 --- a/library/tests/Makefile.am +++ b/library/tests/Makefile.am @@ -5,9 +5,24 @@ INCLUDES = \ -DSRCDIR="\"@abs_srcdir@\"" \ $(NULL) +noinst_LTLIBRARIES = libmock_service.la + +libmock_service_la_SOURCES = \ + mock-service.c mock-service.h \ + $(NULL) + +libmock_service_la_CFLAGS = \ + $(LIBGCRYPT_CFLAGS) + +libmock_service_la_LIBADD = \ + $(top_builddir)/egg/libegg.la \ + $(top_builddir)/library/libgsecret.la \ + $(LIBGCRYPT_LIBS) + LDADD = \ $(top_builddir)/egg/libegg.la \ $(top_builddir)/library/libgsecret.la \ + $(top_builddir)/library/tests/libmock_service.la \ $(NULL) TEST_PROGS = \ diff --git a/library/tests/mock-service.c b/library/tests/mock-service.c new file mode 100644 index 0000000..00f70cc --- /dev/null +++ b/library/tests/mock-service.c @@ -0,0 +1,92 @@ +/* GSecret - GLib wrapper for Secret Service + * + * Copyright 2011 Red Hat Inc. + * + * 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 licence or (at + * your option) any later version. + * + * See the included COPYING file for more information. + * + * Author: Stef Walter + */ + + +#include "config.h" + +#include "mock-service.h" + +#include "gsecret-private.h" + +#include +#include + +static GPid pid = 0; + +gboolean +mock_service_start (const gchar *mock_script, + GError **error) +{ + gchar ready[8] = { 0, }; + GSpawnFlags flags; + int wait_pipe[2]; + GPollFD poll_fd; + gboolean ret; + gint polled; + + gchar *argv[] = { + "python", (gchar *)mock_script, + "--name", MOCK_SERVICE_NAME, + "--ready", ready, + NULL + }; + + g_return_val_if_fail (mock_script != NULL, FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + _gsecret_service_set_default_bus_name (MOCK_SERVICE_NAME); + + if (pipe (wait_pipe) < 0) { + g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (errno), + "Couldn't create pipe for mock service"); + return FALSE; + } + + snprintf (ready, sizeof (ready), "%d", wait_pipe[1]); + + flags = G_SPAWN_SEARCH_PATH | G_SPAWN_LEAVE_DESCRIPTORS_OPEN; + ret = g_spawn_async (SRCDIR, argv, NULL, flags, NULL, NULL, &pid, error); + + close (wait_pipe[1]); + + if (ret) { + poll_fd.events = G_IO_IN | G_IO_HUP | G_IO_ERR; + poll_fd.fd = wait_pipe[0]; + poll_fd.revents = 0; + + polled = g_poll (&poll_fd, 1, 2000); + if (polled < -1) + g_warning ("couldn't poll file descirptor: %s", g_strerror (errno)); + if (polled != 1) + g_warning ("couldn't wait for mock service"); + } + + close (wait_pipe[0]); + return ret; +} + +void +mock_service_stop (void) +{ + if (!pid) + return; + + if (kill (pid, SIGTERM) < 0) { + if (errno != ESRCH) + g_warning ("kill() failed: %s", g_strerror (errno)); + } + + g_spawn_close_pid (pid); + pid = 0; +} diff --git a/library/tests/mock-service.h b/library/tests/mock-service.h new file mode 100644 index 0000000..74ed897 --- /dev/null +++ b/library/tests/mock-service.h @@ -0,0 +1,27 @@ +/* GSecret - GLib wrapper for Secret Service + * + * Copyright 2012 Red Hat Inc. + * + * 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 licence or (at + * your option) any later version. + * + * See the included COPYING file for more information. + * + * Author: Stef Walter + */ + +#ifndef _MOCK_SERVICE_H_ +#define _MOCK_SERVICE_H_ + +#include + +#define MOCK_SERVICE_NAME "org.mock.Service" + +gboolean mock_service_start (const gchar *mock_script, + GError **error); + +void mock_service_stop (void); + +#endif /* _MOCK_SERVICE_H_ */ diff --git a/library/tests/mock/service.py b/library/tests/mock/service.py index 6a49382..35892dd 100644 --- a/library/tests/mock/service.py +++ b/library/tests/mock/service.py @@ -29,6 +29,7 @@ import gobject COLLECTION_PREFIX = "/org/freedesktop/secrets/collection/" bus_name = 'org.freedesktop.Secret.MockService' +ready_pipe = -1 objects = { } class NotSupported(dbus.exceptions.DBusException): @@ -261,7 +262,12 @@ class SecretService(dbus.service.Object): SecretItem(collection, "item_three", attributes={ "number": "3", "string": "three", "parity": "odd" }) def listen(self): + global ready_pipe loop = gobject.MainLoop() + if ready_pipe >= 0: + os.write(ready_pipe, "GO") + os.close(ready_pipe) + ready_pipe = -1 loop.run() def add_session(self, session): @@ -323,15 +329,17 @@ class SecretService(dbus.service.Object): def parse_options(args): - global bus_name + global bus_name, ready_pipe try: - opts, args = getopt.getopt(args, "name", ["name="]) + opts, args = getopt.getopt(args, "nr", ["name=", "ready="]) except getopt.GetoptError, err: print str(err) sys.exit(2) for o, a in opts: - if o in ("--name"): + if o in ("-n", "--name"): bus_name = a + elif o in ("-r", "--ready"): + ready_pipe = int(a) else: assert False, "unhandled option" return args diff --git a/library/tests/test-password.c b/library/tests/test-password.c index cc93cf7..79d8f3a 100644 --- a/library/tests/test-password.c +++ b/library/tests/test-password.c @@ -17,6 +17,8 @@ #include "gsecret-password.h" #include "gsecret-private.h" +#include "mock-service.h" + #include "egg/egg-testing.h" #include @@ -24,8 +26,6 @@ #include #include -static gchar *MOCK_NAME = "org.mock.Service"; - static const GSecretSchema DELETE_SCHEMA = { "org.mock.schema.Delete", { @@ -45,27 +45,16 @@ setup (Test *test, { GError *error = NULL; const gchar *mock_script = data; - gchar *argv[] = { - "python", (gchar *)mock_script, - "--name", MOCK_NAME, - NULL - }; - _gsecret_service_set_default_bus_name (MOCK_NAME); - - g_spawn_async (SRCDIR, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, &test->pid, &error); + mock_service_start (mock_script, &error); g_assert_no_error (error); - g_usleep (200 * 1000); } static void teardown (Test *test, gconstpointer unused) { - g_assert (test->pid); - if (kill (test->pid, SIGTERM) < 0) - g_error ("kill() failed: %s", g_strerror (errno)); - g_spawn_close_pid (test->pid); + mock_service_stop (); } static void diff --git a/library/tests/test-prompt.c b/library/tests/test-prompt.c index 66da890..7283076 100644 --- a/library/tests/test-prompt.c +++ b/library/tests/test-prompt.c @@ -20,6 +20,8 @@ #include "gsecret-private.h" #include "gsecret-prompt.h" +#include "mock-service.h" + #include "egg/egg-testing.h" #include @@ -27,10 +29,7 @@ #include #include -static gchar *MOCK_NAME = "org.mock.Service"; - typedef struct { - GPid pid; GDBusConnection *connection; GSecretService *service; } Test; @@ -41,17 +40,9 @@ setup (Test *test, { GError *error = NULL; const gchar *mock_script = data; - gchar *argv[] = { - "python", (gchar *)mock_script, - "--name", MOCK_NAME, - NULL - }; - _gsecret_service_set_default_bus_name (MOCK_NAME); - - g_spawn_async (SRCDIR, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, &test->pid, &error); + mock_service_start (mock_script, &error); g_assert_no_error (error); - g_usleep (200 * 1000); test->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); g_assert_no_error (error); @@ -68,12 +59,7 @@ teardown (Test *test, g_object_unref (test->service); egg_assert_not_object (test->service); - g_assert (test->pid); - if (kill (test->pid, SIGTERM) < 0) { - if (errno != ESRCH) - g_error ("kill() failed: %s", g_strerror (errno)); - } - g_spawn_close_pid (test->pid); + mock_service_stop (); g_dbus_connection_flush_sync (test->connection, NULL, &error); g_assert_no_error (error); diff --git a/library/tests/test-service.c b/library/tests/test-service.c index 7937ae2..61f7b8e 100644 --- a/library/tests/test-service.c +++ b/library/tests/test-service.c @@ -16,6 +16,8 @@ #include "gsecret-service.h" #include "gsecret-private.h" +#include "mock-service.h" + #include "egg/egg-testing.h" #include @@ -46,17 +48,9 @@ setup_mock (Test *test, { GError *error = NULL; const gchar *mock_script = data; - gchar *argv[] = { - "python", (gchar *)mock_script, - "--name", MOCK_NAME, - NULL - }; - _gsecret_service_set_default_bus_name (MOCK_NAME); - - g_spawn_async (SRCDIR, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, &test->pid, &error); + mock_service_start (mock_script, &error); g_assert_no_error (error); - g_usleep (200 * 1000); } static void @@ -77,10 +71,7 @@ static void teardown_mock (Test *test, gconstpointer unused) { - g_assert (test->pid); - if (kill (test->pid, SIGTERM) < 0) - g_error ("kill() failed: %s", g_strerror (errno)); - g_spawn_close_pid (test->pid); + mock_service_stop (); } static void diff --git a/library/tests/test-session.c b/library/tests/test-session.c index 98df7be..08c689d 100644 --- a/library/tests/test-session.c +++ b/library/tests/test-session.c @@ -17,6 +17,8 @@ #include "gsecret-service.h" #include "gsecret-private.h" +#include "mock-service.h" + #include "egg/egg-testing.h" #include @@ -24,8 +26,6 @@ #include #include -static gchar *MOCK_NAME = "org.mock.Service"; - typedef struct { GPid pid; GDBusConnection *connection; @@ -38,17 +38,9 @@ setup (Test *test, { GError *error = NULL; const gchar *mock_script = data; - gchar *argv[] = { - "python", (gchar *)mock_script, - "--name", MOCK_NAME, - NULL - }; - _gsecret_service_set_default_bus_name (MOCK_NAME); - - g_spawn_async (SRCDIR, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, &test->pid, &error); + mock_service_start (mock_script, &error); g_assert_no_error (error); - g_usleep (200 * 1000); test->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); g_assert_no_error (error); @@ -65,10 +57,7 @@ teardown (Test *test, g_object_unref (test->service); egg_assert_not_object (test->service); - g_assert (test->pid); - if (kill (test->pid, SIGTERM) < 0) - g_error ("kill() failed: %s", g_strerror (errno)); - g_spawn_close_pid (test->pid); + mock_service_stop (); g_dbus_connection_flush_sync (test->connection, NULL, &error); g_assert_no_error (error);