mirror of
https://gitlab.gnome.org/GNOME/libsecret.git
synced 2024-12-22 20:58:52 +00:00
libsecret: Fix up the tests for recent regressions
This commit is contained in:
parent
70d1bc3307
commit
ad77f143e6
@ -23,86 +23,118 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.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 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,
|
service_start (const gchar *mock_script,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
gchar ready[8] = { 0, };
|
|
||||||
GSpawnFlags flags;
|
GSpawnFlags flags;
|
||||||
int wait_pipe[2];
|
|
||||||
GPollFD poll_fd;
|
|
||||||
gboolean ret;
|
gboolean ret;
|
||||||
gint polled;
|
gint output;
|
||||||
|
|
||||||
gchar *argv[] = {
|
gchar *argv[] = {
|
||||||
"python", (gchar *)mock_script,
|
"python", (gchar *)mock_script,
|
||||||
"--name", MOCK_SERVICE_NAME,
|
|
||||||
"--ready", ready,
|
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
g_return_val_if_fail (mock_script != NULL, FALSE);
|
g_return_val_if_fail (mock_script != NULL, FALSE);
|
||||||
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||||
|
|
||||||
test_bus = g_test_dbus_new (G_TEST_DBUS_NONE);
|
g_free (service_name);
|
||||||
g_test_dbus_up (test_bus);
|
service_name = NULL;
|
||||||
|
|
||||||
g_setenv ("SECRET_SERVICE_BUS_NAME", MOCK_SERVICE_NAME, TRUE);
|
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,
|
||||||
if (pipe (wait_pipe) < 0) {
|
NULL, &output, NULL, error);
|
||||||
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) {
|
if (ret) {
|
||||||
poll_fd.events = G_IO_IN | G_IO_HUP | G_IO_ERR;
|
service_name = read_until_end (output, error);
|
||||||
poll_fd.fd = wait_pipe[0];
|
if (service_name) {
|
||||||
poll_fd.revents = 0;
|
g_strstrip (service_name);
|
||||||
|
g_assert_cmpstr (service_name, !=, "");
|
||||||
polled = g_poll (&poll_fd, 1, 2000);
|
g_setenv ("SECRET_SERVICE_BUS_NAME", service_name, TRUE);
|
||||||
if (polled < -1)
|
}
|
||||||
g_warning ("couldn't poll file descirptor: %s", g_strerror (errno));
|
close (output);
|
||||||
if (polled != 1)
|
|
||||||
g_warning ("couldn't wait for mock service");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
close (wait_pipe[0]);
|
return service_name;
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
const gchar *
|
||||||
mock_service_start (const gchar *mock_script,
|
mock_service_start (const gchar *mock_script,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
gchar *path;
|
gchar *path;
|
||||||
gboolean ret;
|
const gchar *name;
|
||||||
|
|
||||||
path = g_build_filename (SRCDIR, "libsecret", mock_script, NULL);
|
path = g_build_filename (SRCDIR, "libsecret", mock_script, NULL);
|
||||||
ret = service_start (path, error);
|
name = service_start (path, error);
|
||||||
g_free (path);
|
g_free (path);
|
||||||
|
|
||||||
return ret;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
mock_service_stop (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 (kill (pid, SIGTERM) < 0) {
|
||||||
if (errno != ESRCH)
|
if (errno != ESRCH)
|
||||||
g_warning ("kill() failed: %s", g_strerror (errno));
|
g_warning ("kill() failed: %s", g_strerror (errno));
|
||||||
@ -110,21 +142,8 @@ mock_service_stop (void)
|
|||||||
|
|
||||||
g_spawn_close_pid (pid);
|
g_spawn_close_pid (pid);
|
||||||
pid = 0;
|
pid = 0;
|
||||||
|
}
|
||||||
|
|
||||||
while (g_main_context_iteration (NULL, FALSE));
|
while (g_main_context_iteration (NULL, FALSE));
|
||||||
|
g_unsetenv ("SECRET_SERVICE_BUS_NAME");
|
||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
}
|
||||||
|
@ -17,9 +17,7 @@
|
|||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|
||||||
#define MOCK_SERVICE_NAME "org.mock.Service"
|
const gchar * mock_service_start (const gchar *mock_script,
|
||||||
|
|
||||||
gboolean mock_service_start (const gchar *mock_script,
|
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
void mock_service_stop (void);
|
void mock_service_stop (void);
|
||||||
|
@ -28,8 +28,6 @@ import gobject
|
|||||||
|
|
||||||
COLLECTION_PREFIX = "/org/freedesktop/secrets/collection/"
|
COLLECTION_PREFIX = "/org/freedesktop/secrets/collection/"
|
||||||
|
|
||||||
bus_name = 'org.freedesktop.Secret.MockService'
|
|
||||||
ready_pipe = -1
|
|
||||||
objects = { }
|
objects = { }
|
||||||
|
|
||||||
class NotSupported(dbus.exceptions.DBusException):
|
class NotSupported(dbus.exceptions.DBusException):
|
||||||
@ -132,7 +130,7 @@ class SecretPrompt(dbus.service.Object):
|
|||||||
self.path = "/org/freedesktop/secrets/prompts/%s" % prompt_name
|
self.path = "/org/freedesktop/secrets/prompts/%s" % prompt_name
|
||||||
else:
|
else:
|
||||||
self.path = "/org/freedesktop/secrets/prompts/%s" % next_identifier('p')
|
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)
|
service.add_prompt(self)
|
||||||
assert self.path not in objects
|
assert self.path not in objects
|
||||||
objects[self.path] = self
|
objects[self.path] = self
|
||||||
@ -166,7 +164,7 @@ class SecretSession(dbus.service.Object):
|
|||||||
self.algorithm = algorithm
|
self.algorithm = algorithm
|
||||||
self.key = key
|
self.key = key
|
||||||
self.path = "/org/freedesktop/secrets/sessions/%s" % next_identifier('s')
|
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)
|
service.add_session(self)
|
||||||
objects[self.path] = self
|
objects[self.path] = self
|
||||||
|
|
||||||
@ -206,7 +204,7 @@ class SecretItem(dbus.service.Object):
|
|||||||
self.path = "%s/%s" % (collection.path, identifier)
|
self.path = "%s/%s" % (collection.path, identifier)
|
||||||
self.confirm = confirm
|
self.confirm = confirm
|
||||||
self.created = self.modified = time.time()
|
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)
|
self.collection.add_item(self)
|
||||||
objects[self.path] = self
|
objects[self.path] = self
|
||||||
|
|
||||||
@ -327,7 +325,7 @@ class SecretCollection(dbus.service.Object):
|
|||||||
self.created = self.modified = time.time()
|
self.created = self.modified = time.time()
|
||||||
self.aliased = set()
|
self.aliased = set()
|
||||||
self.path = "%s%s" % (COLLECTION_PREFIX, identifier)
|
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)
|
self.service.add_collection(self)
|
||||||
objects[self.path] = self
|
objects[self.path] = self
|
||||||
|
|
||||||
@ -476,12 +474,9 @@ class SecretService(dbus.service.Object):
|
|||||||
"dh-ietf1024-sha256-aes128-cbc-pkcs7": AesAlgorithm(),
|
"dh-ietf1024-sha256-aes128-cbc-pkcs7": AesAlgorithm(),
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, name=None):
|
def __init__(self):
|
||||||
if name == None:
|
self.bus = dbus.SessionBus()
|
||||||
name = bus_name
|
dbus.service.Object.__init__(self, self.bus, '/org/freedesktop/secrets')
|
||||||
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')
|
|
||||||
self.sessions = { }
|
self.sessions = { }
|
||||||
self.prompts = { }
|
self.prompts = { }
|
||||||
self.collections = { }
|
self.collections = { }
|
||||||
@ -493,9 +488,7 @@ class SecretService(dbus.service.Object):
|
|||||||
for session in list(self.sessions.get(old_owner, [])):
|
for session in list(self.sessions.get(old_owner, [])):
|
||||||
session.Close()
|
session.Close()
|
||||||
|
|
||||||
bus.add_signal_receiver(on_name_owner_changed,
|
self.bus.add_signal_receiver(on_name_owner_changed, 'NameOwnerChanged', 'org.freedesktop.DBus')
|
||||||
'NameOwnerChanged',
|
|
||||||
'org.freedesktop.DBus')
|
|
||||||
|
|
||||||
def add_standard_objects(self):
|
def add_standard_objects(self):
|
||||||
collection = SecretCollection(self, "english", label="Collection One", locked=False)
|
collection = SecretCollection(self, "english", label="Collection One", locked=False)
|
||||||
@ -532,12 +525,12 @@ class SecretService(dbus.service.Object):
|
|||||||
self.set_alias('session', collection)
|
self.set_alias('session', collection)
|
||||||
|
|
||||||
def listen(self):
|
def listen(self):
|
||||||
global ready_pipe
|
|
||||||
loop = gobject.MainLoop()
|
loop = gobject.MainLoop()
|
||||||
if ready_pipe >= 0:
|
name = self.bus.get_unique_name()
|
||||||
os.write(ready_pipe, "GO")
|
if not name:
|
||||||
os.close(ready_pipe)
|
raise NameError("No unique name available")
|
||||||
ready_pipe = -1
|
print name
|
||||||
|
sys.stdout.flush()
|
||||||
loop.run()
|
loop.run()
|
||||||
|
|
||||||
def add_session(self, session):
|
def add_session(self, session):
|
||||||
@ -696,18 +689,12 @@ class SecretService(dbus.service.Object):
|
|||||||
|
|
||||||
|
|
||||||
def parse_options(args):
|
def parse_options(args):
|
||||||
global bus_name, ready_pipe
|
|
||||||
try:
|
try:
|
||||||
opts, args = getopt.getopt(args, "nr", ["name=", "ready="])
|
opts, args = getopt.getopt(args, "", [])
|
||||||
except getopt.GetoptError, err:
|
except getopt.GetoptError, err:
|
||||||
print str(err)
|
print str(err)
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
for o, a in opts:
|
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
|
return args
|
||||||
|
|
||||||
|
@ -47,8 +47,17 @@ static void
|
|||||||
teardown_mock (Test *test,
|
teardown_mock (Test *test,
|
||||||
gconstpointer unused)
|
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 ();
|
secret_service_disconnect ();
|
||||||
mock_service_stop ();
|
mock_service_stop ();
|
||||||
|
|
||||||
|
while (g_main_context_iteration (NULL, FALSE));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -98,6 +107,10 @@ test_get_sync (Test *test,
|
|||||||
g_object_add_weak_pointer (G_OBJECT (service3), (gpointer *)&service3);
|
g_object_add_weak_pointer (G_OBJECT (service3), (gpointer *)&service3);
|
||||||
|
|
||||||
g_object_unref (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 ();
|
secret_service_disconnect ();
|
||||||
g_assert (service3 == NULL);
|
g_assert (service3 == NULL);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user