[libsecret] libsecret: Fix up the tests for recent regressions



commit ad77f143e61401a16140aec8798d3495052e1c56
Author: Stef Walter <stefw redhat com>
Date:   Tue Apr 14 10:48:19 2015 +0200

    libsecret: Fix up the tests for recent regressions

 libsecret/mock-service.c  |  145 +++++++++++++++++++++++++-------------------
 libsecret/mock-service.h  |    4 +-
 libsecret/mock/service.py |   43 +++++---------
 libsecret/test-service.c  |   13 ++++
 4 files changed, 111 insertions(+), 94 deletions(-)
---
diff --git a/libsecret/mock-service.c b/libsecret/mock-service.c
index 68baec4..f890f1d 100644
--- a/libsecret/mock-service.c
+++ b/libsecret/mock-service.c
@@ -23,108 +23,127 @@
 #include <stdio.h>
 #include <string.h>
 
-static GTestDBus *test_bus = NULL;
+#ifdef __linux
+#include <sys/prctl.h>
+#endif
+
+static gchar *service_name = NULL;
 static GPid pid = 0;
 
-static gboolean
+static void
+on_python_child_setup (gpointer user_data)
+{
+#ifdef __linux
+  prctl (PR_SET_PDEATHSIG, 15);
+#endif
+}
+
+static gchar *
+read_until_end (int fd,
+                GError **error)
+{
+       GString *data;
+       gsize len;
+       gssize ret;
+       gchar *pos;
+
+       data = g_string_new ("");
+
+       for (;;) {
+               len = data->len;
+               g_string_set_size (data, len + 256);
+               ret = read (fd, data->str + len, 256);
+               if (ret < 0) {
+                       if (errno != EAGAIN) {
+                               g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno),
+                                            "Couldn't read from mock service: %s", g_strerror (errno));
+                               g_string_free (data, TRUE);
+                               return NULL;
+                       }
+               } else if (ret == 0) {
+                       g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Remote closed the output");
+                       g_string_free (data, TRUE);
+                       return NULL;
+               } else {
+                       data->len = len + ret;
+                       data->str[data->len] = '\0';
+               }
+
+               pos = strchr (data->str, '\n');
+               if (pos) {
+                       g_string_set_size (data, pos - data->str);
+                       break;
+               }
+       }
+
+       return g_string_free (data, FALSE);
+}
+
+static const gchar *
 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;
+       gint output;
 
        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);
 
-       test_bus = g_test_dbus_new (G_TEST_DBUS_NONE);
-       g_test_dbus_up (test_bus);
+       g_free (service_name);
+       service_name = NULL;
 
-       g_setenv ("SECRET_SERVICE_BUS_NAME", MOCK_SERVICE_NAME, TRUE);
-
-       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]);
+       flags = G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD;
+       ret = g_spawn_async_with_pipes (SRCDIR, argv, NULL, flags, on_python_child_setup, NULL, &pid,
+                                       NULL, &output, NULL, error);
 
        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");
+               service_name = read_until_end (output, error);
+               if (service_name) {
+                       g_strstrip (service_name);
+                       g_assert_cmpstr (service_name, !=, "");
+                       g_setenv ("SECRET_SERVICE_BUS_NAME", service_name, TRUE);
+               }
+               close (output);
        }
 
-       close (wait_pipe[0]);
-       return ret;
+       return service_name;
 }
 
-gboolean
+const gchar *
 mock_service_start (const gchar *mock_script,
                     GError **error)
 {
        gchar *path;
-       gboolean ret;
+       const gchar *name;
 
        path = g_build_filename (SRCDIR, "libsecret", mock_script, NULL);
-       ret = service_start (path, error);
+       name = service_start (path, error);
        g_free (path);
 
-       return ret;
+       return name;
 }
 
 void
 mock_service_stop (void)
 {
-       const gchar *prgname;
+       while (g_main_context_iteration (NULL, FALSE));
 
-       if (!pid)
-               return;
+       if (pid) {
+               if (kill (pid, SIGTERM) < 0) {
+                       if (errno != ESRCH)
+                               g_warning ("kill() failed: %s", g_strerror (errno));
+               }
 
-       if (kill (pid, SIGTERM) < 0) {
-               if (errno != ESRCH)
-                       g_warning ("kill() failed: %s", g_strerror (errno));
+               g_spawn_close_pid (pid);
+               pid = 0;
        }
 
-       g_spawn_close_pid (pid);
-       pid = 0;
-
        while (g_main_context_iteration (NULL, FALSE));
-
-       /*
-        * HACK: Don't worry about leaking tests when running under gjs.
-        * Waiting for the connection to go away is hopeless due to
-        * the way gjs garbage collects.
-        */
-       prgname = g_get_prgname ();
-       if (prgname && strstr (prgname, "gjs")) {
-               g_test_dbus_stop (test_bus);
-
-       } else {
-               g_test_dbus_down (test_bus);
-               g_object_unref (test_bus);
-       }
-       test_bus = NULL;
+       g_unsetenv ("SECRET_SERVICE_BUS_NAME");
 }
diff --git a/libsecret/mock-service.h b/libsecret/mock-service.h
index a160de9..f098c32 100644
--- a/libsecret/mock-service.h
+++ b/libsecret/mock-service.h
@@ -17,9 +17,7 @@
 
 #include <glib.h>
 
-#define MOCK_SERVICE_NAME "org.mock.Service"
-
-gboolean      mock_service_start     (const gchar *mock_script,
+const gchar * mock_service_start     (const gchar *mock_script,
                                       GError **error);
 
 void          mock_service_stop      (void);
diff --git a/libsecret/mock/service.py b/libsecret/mock/service.py
index 14661a1..d8f7e66 100644
--- a/libsecret/mock/service.py
+++ b/libsecret/mock/service.py
@@ -28,8 +28,6 @@ import gobject
 
 COLLECTION_PREFIX = "/org/freedesktop/secrets/collection/"
 
-bus_name = 'org.freedesktop.Secret.MockService'
-ready_pipe = -1
 objects = { }
 
 class NotSupported(dbus.exceptions.DBusException):
@@ -132,7 +130,7 @@ class SecretPrompt(dbus.service.Object):
                        self.path = "/org/freedesktop/secrets/prompts/%s" % prompt_name
                else:
                        self.path = "/org/freedesktop/secrets/prompts/%s" % next_identifier('p')
-               dbus.service.Object.__init__(self, service.bus_name, self.path)
+               dbus.service.Object.__init__(self, service.bus, self.path)
                service.add_prompt(self)
                assert self.path not in objects
                objects[self.path] = self
@@ -166,7 +164,7 @@ class SecretSession(dbus.service.Object):
                self.algorithm = algorithm
                self.key = key
                self.path = "/org/freedesktop/secrets/sessions/%s" % next_identifier('s')
-               dbus.service.Object.__init__(self, service.bus_name, self.path)
+               dbus.service.Object.__init__(self, service.bus, self.path)
                service.add_session(self)
                objects[self.path] = self
 
@@ -206,7 +204,7 @@ class SecretItem(dbus.service.Object):
                self.path = "%s/%s" % (collection.path, identifier)
                self.confirm = confirm
                self.created = self.modified = time.time()
-               dbus.service.Object.__init__(self, collection.service.bus_name, self.path)
+               dbus.service.Object.__init__(self, collection.service.bus, self.path)
                self.collection.add_item(self)
                objects[self.path] = self
 
@@ -327,7 +325,7 @@ class SecretCollection(dbus.service.Object):
                self.created = self.modified = time.time()
                self.aliased = set()
                self.path = "%s%s" % (COLLECTION_PREFIX, identifier)
-               dbus.service.Object.__init__(self, service.bus_name, self.path)
+               dbus.service.Object.__init__(self, service.bus, self.path)
                self.service.add_collection(self)
                objects[self.path] = self
 
@@ -476,12 +474,9 @@ class SecretService(dbus.service.Object):
                "dh-ietf1024-sha256-aes128-cbc-pkcs7": AesAlgorithm(),
        }
 
-       def __init__(self, name=None):
-               if name == None:
-                       name = bus_name
-               bus = dbus.SessionBus()
-               self.bus_name = dbus.service.BusName(name, allow_replacement=True, replace_existing=True)
-               dbus.service.Object.__init__(self, self.bus_name, '/org/freedesktop/secrets')
+       def __init__(self):
+               self.bus = dbus.SessionBus()
+               dbus.service.Object.__init__(self, self.bus, '/org/freedesktop/secrets')
                self.sessions = { }
                self.prompts = { }
                self.collections = { }
@@ -493,9 +488,7 @@ class SecretService(dbus.service.Object):
                                for session in list(self.sessions.get(old_owner, [])):
                                        session.Close()
 
-               bus.add_signal_receiver(on_name_owner_changed,
-                                       'NameOwnerChanged',
-                                       'org.freedesktop.DBus')
+               self.bus.add_signal_receiver(on_name_owner_changed, 'NameOwnerChanged', 
'org.freedesktop.DBus')
 
        def add_standard_objects(self):
                collection = SecretCollection(self, "english", label="Collection One", locked=False)
@@ -532,12 +525,12 @@ class SecretService(dbus.service.Object):
                self.set_alias('session', collection)
 
        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
+               name = self.bus.get_unique_name()
+               if not name:
+                       raise NameError("No unique name available")
+               print name
+               sys.stdout.flush()
                loop.run()
 
        def add_session(self, session):
@@ -696,19 +689,13 @@ class SecretService(dbus.service.Object):
 
 
 def parse_options(args):
-       global bus_name, ready_pipe
        try:
-               opts, args = getopt.getopt(args, "nr", ["name=", "ready="])
+               opts, args = getopt.getopt(args, "", [])
        except getopt.GetoptError, err:
                print str(err)
                sys.exit(2)
        for o, a in opts:
-               if o in ("-n", "--name"):
-                       bus_name = a
-               elif o in ("-r", "--ready"):
-                       ready_pipe = int(a)
-               else:
-                       assert False, "unhandled option"
+               assert False, "unhandled option"
        return args
 
 parse_options(sys.argv[1:])
diff --git a/libsecret/test-service.c b/libsecret/test-service.c
index aa1a395..c081275 100644
--- a/libsecret/test-service.c
+++ b/libsecret/test-service.c
@@ -47,8 +47,17 @@ static void
 teardown_mock (Test *test,
                gconstpointer unused)
 {
+       /*
+        * Because the entire model of GDBus using another worker-thread
+        * is shit and racy as hell. If I had more time I would fix GDBus not to segfault
+        * during tests, but for now this is the best I can do.
+        */
+       g_usleep (G_USEC_PER_SEC);
+
        secret_service_disconnect ();
        mock_service_stop ();
+
+       while (g_main_context_iteration (NULL, FALSE));
 }
 
 static void
@@ -98,6 +107,10 @@ test_get_sync (Test *test,
        g_object_add_weak_pointer (G_OBJECT (service3), (gpointer *)&service3);
 
        g_object_unref (service3);
+
+       /* Because the entire model of GDBus using another worker-thread is shite */
+       g_usleep (G_USEC_PER_SEC);
+
        secret_service_disconnect ();
        g_assert (service3 == NULL);
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]