Commit f5afec02 authored by Simon McVittie's avatar Simon McVittie

test-utils-glib: Add failable functions to connect to a bus

Instead of calling g_test_skip() internally, raise a distinctive error
and let the caller handle it.
Signed-off-by: Simon McVittie's avatarSimon McVittie <smcv@collabora.com>
Reviewed-by: Philip Withnall's avatarPhilip Withnall <withnall@endlessm.com>
Bug: https://bugs.freedesktop.org/show_bug.cgi?id=101354
parent f58b77f9
......@@ -42,6 +42,7 @@
#include <glib.h>
#include <glib/gstdio.h>
#include <gio/gio.h>
#include <dbus/dbus.h>
......@@ -318,28 +319,53 @@ test_get_dbus_daemon (const gchar *config_file,
DBusConnection *
test_connect_to_bus (TestMainContext *ctx,
const gchar *address)
{
GError *error = NULL;
DBusConnection *conn = test_try_connect_to_bus (ctx, address, &error);
g_assert_no_error (error);
g_assert (conn != NULL);
return conn;
}
DBusConnection *
test_try_connect_to_bus (TestMainContext *ctx,
const gchar *address,
GError **gerror)
{
DBusConnection *conn;
DBusError error = DBUS_ERROR_INIT;
dbus_bool_t ok;
conn = dbus_connection_open_private (address, &error);
test_assert_no_error (&error);
g_assert (conn != NULL);
ok = dbus_bus_register (conn, &error);
test_assert_no_error (&error);
g_assert (ok);
if (conn == NULL)
goto fail;
if (!dbus_bus_register (conn, &error))
goto fail;
g_assert (dbus_bus_get_unique_name (conn) != NULL);
test_connection_setup (ctx, conn);
return conn;
fail:
if (gerror != NULL)
*gerror = g_dbus_error_new_for_dbus_error (error.name, error.message);
dbus_error_free (&error);
return FALSE;
}
/*
* Raise G_IO_ERROR_NOT_SUPPORTED if the requested user is impossible.
* Do not mark the test as skipped: we might have more to test anyway.
*/
DBusConnection *
test_connect_to_bus_as_user (TestMainContext *ctx,
test_try_connect_to_bus_as_user (TestMainContext *ctx,
const char *address,
TestUser user)
TestUser user,
GError **error)
{
/* For now we only do tests like this on Linux, because I don't know how
* safe this use of setresuid() is on other platforms */
......@@ -352,7 +378,7 @@ test_connect_to_bus_as_user (TestMainContext *ctx,
switch (user)
{
case TEST_USER_ME:
return test_connect_to_bus (ctx, address);
return test_try_connect_to_bus (ctx, address, error);
case TEST_USER_ROOT:
username = "root";
......@@ -375,9 +401,9 @@ test_connect_to_bus_as_user (TestMainContext *ctx,
if (ruid != 0 || euid != 0 || suid != 0)
{
g_test_message ("not uid 0 (ruid=%ld euid=%ld suid=%ld)",
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
"not uid 0 (ruid=%ld euid=%ld suid=%ld)",
(unsigned long) ruid, (unsigned long) euid, (unsigned long) suid);
g_test_skip ("not uid 0");
return NULL;
}
......@@ -385,13 +411,13 @@ test_connect_to_bus_as_user (TestMainContext *ctx,
if (pwd == NULL)
{
g_test_message ("getpwnam(\"%s\"): %s", username, g_strerror (errno));
g_test_skip ("not uid 0");
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
"getpwnam(\"%s\"): %s", username, g_strerror (errno));
return NULL;
}
/* Impersonate the desired user while we connect to the bus.
* This should work, because we're root. */
* This should work, because we're root; so if it fails, we just crash. */
if (setresuid (pwd->pw_uid, pwd->pw_uid, 0) != 0)
g_error ("setresuid(%ld, (same), 0): %s",
(unsigned long) pwd->pw_uid, g_strerror (errno));
......@@ -409,12 +435,13 @@ test_connect_to_bus_as_user (TestMainContext *ctx,
switch (user)
{
case TEST_USER_ME:
return test_connect_to_bus (ctx, address);
return test_try_connect_to_bus (ctx, address, error);
case TEST_USER_ROOT:
case TEST_USER_MESSAGEBUS:
case TEST_USER_OTHER:
g_test_skip ("setresuid() not available, or unsure about "
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
"setresuid() not available, or unsure about "
"credentials-passing semantics on this platform");
return NULL;
......
......@@ -74,9 +74,13 @@ gchar *test_get_dbus_daemon (const gchar *config_file,
DBusConnection *test_connect_to_bus (TestMainContext *ctx,
const gchar *address);
DBusConnection *test_connect_to_bus_as_user (TestMainContext *ctx,
DBusConnection *test_try_connect_to_bus (TestMainContext *ctx,
const gchar *address,
GError **error);
DBusConnection *test_try_connect_to_bus_as_user (TestMainContext *ctx,
const char *address,
TestUser user);
TestUser user,
GError **error);
void test_kill_pid (GPid pid);
......
......@@ -29,6 +29,8 @@
#include "test-utils-glib.h"
#include <gio/gio.h>
typedef struct {
gboolean skip;
......@@ -69,12 +71,18 @@ setup (Fixture *f,
return;
}
f->conn = test_connect_to_bus_as_user (f->ctx, address,
config ? config->user : TEST_USER_ME);
f->conn = test_try_connect_to_bus_as_user (f->ctx, address,
config ? config->user : TEST_USER_ME, &f->ge);
if (f->conn == NULL)
f->skip = TRUE;
if (f->conn == NULL &&
g_error_matches (f->ge, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED))
{
g_test_skip (f->ge->message);
g_clear_error (&f->ge);
f->skip = TRUE;
}
g_assert_no_error (f->ge);
g_free (address);
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment