glib/gio/tests/gdbus-auth.c
Philip Withnall 404d5d40e0 tests: Ensure timeout source is removed in gdbus-auth test
If the whole set of tests takes more than 5 seconds, the failure timeout
from the first test could still trigger, causing an incorrect failure.

Ensure the timeout is removed at the end of each test.i

This will hopefully fix the CI failure seen here:
https://gitlab.gnome.org/pwithnall/glib/-/jobs/1879558.
```
204/266 glib:gio / gdbus-auth                   FAIL     9.21 s (killed by signal 5 SIGTRAP)
…
ok 1 /gdbus/auth/client/EXTERNAL
Bail out! GLib-GIO-FATAL-ERROR: Timeout waiting for client
```

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2022-03-11 23:47:22 +00:00

315 lines
8.5 KiB
C

/* GLib testing framework examples and tests
*
* Copyright (C) 2008-2013 Red Hat, Inc.
*
* This library 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.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
*
* Author: David Zeuthen <davidz@redhat.com>
*/
#include <locale.h>
#include <gio/gio.h>
#include <string.h>
#include <unistd.h>
#include "gdbus-tests.h"
#ifdef G_OS_UNIX
#include <gio/gunixconnection.h>
#include <gio/gnetworkingprivate.h>
#include <gio/gunixsocketaddress.h>
#include <gio/gunixfdlist.h>
#endif
/* ---------------------------------------------------------------------------------------------------- */
static gboolean
server_on_allow_mechanism (GDBusAuthObserver *observer,
const gchar *mechanism,
gpointer user_data)
{
const gchar *allowed_mechanism = user_data;
if (allowed_mechanism == NULL || g_strcmp0 (mechanism, allowed_mechanism) == 0)
return TRUE;
else
return FALSE;
}
/* pass NULL to allow any mechanism */
static GDBusServer *
server_new_for_mechanism (const gchar *allowed_mechanism)
{
gchar *addr;
gchar *guid;
GDBusServer *server;
GDBusAuthObserver *auth_observer;
GError *error;
GDBusServerFlags flags;
guid = g_dbus_generate_guid ();
#ifdef G_OS_UNIX
if (g_unix_socket_address_abstract_names_supported ())
{
addr = g_strdup ("unix:tmpdir=/tmp/gdbus-test-");
}
else
{
gchar *tmpdir;
tmpdir = g_dir_make_tmp ("gdbus-test-XXXXXX", NULL);
addr = g_strdup_printf ("unix:tmpdir=%s", tmpdir);
g_free (tmpdir);
}
#else
addr = g_strdup ("nonce-tcp:");
#endif
auth_observer = g_dbus_auth_observer_new ();
flags = G_DBUS_SERVER_FLAGS_NONE;
if (g_strcmp0 (allowed_mechanism, "ANONYMOUS") == 0)
flags |= G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS;
error = NULL;
server = g_dbus_server_new_sync (addr,
flags,
guid,
auth_observer,
NULL, /* cancellable */
&error);
g_assert_no_error (error);
g_assert (server != NULL);
g_signal_connect (auth_observer,
"allow-mechanism",
G_CALLBACK (server_on_allow_mechanism),
(gpointer) allowed_mechanism);
g_free (addr);
g_free (guid);
g_object_unref (auth_observer);
return server;
}
/* ---------------------------------------------------------------------------------------------------- */
static gboolean
test_auth_on_new_connection (GDBusServer *server,
GDBusConnection *connection,
gpointer user_data)
{
GMainLoop *loop = user_data;
g_main_loop_quit (loop);
return FALSE;
}
static gboolean
test_auth_on_timeout (gpointer user_data)
{
g_error ("Timeout waiting for client");
g_assert_not_reached ();
return G_SOURCE_REMOVE;
}
typedef struct
{
const gchar *address;
const gchar *allowed_client_mechanism;
const gchar *allowed_server_mechanism;
} TestAuthData;
static gpointer
test_auth_client_thread_func (gpointer user_data)
{
TestAuthData *data = user_data;
GDBusConnection *c = NULL;
GError *error = NULL;
GDBusAuthObserver *auth_observer = NULL;
auth_observer = g_dbus_auth_observer_new ();
g_signal_connect (auth_observer,
"allow-mechanism",
G_CALLBACK (server_on_allow_mechanism),
(gpointer) data->allowed_client_mechanism);
c = g_dbus_connection_new_for_address_sync (data->address,
G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
auth_observer,
NULL, /* GCancellable */
&error);
g_assert_no_error (error);
g_assert (c != NULL);
g_clear_object (&c);
g_clear_object (&auth_observer);
return NULL;
}
static void
test_auth_mechanism (const gchar *allowed_client_mechanism,
const gchar *allowed_server_mechanism)
{
GDBusServer *server;
GMainLoop *loop;
GThread *client_thread;
TestAuthData data;
guint timeout_id;
server = server_new_for_mechanism (allowed_server_mechanism);
loop = g_main_loop_new (NULL, FALSE);
g_signal_connect (server,
"new-connection",
G_CALLBACK (test_auth_on_new_connection),
loop);
timeout_id = g_timeout_add_seconds (5, test_auth_on_timeout, NULL);
data.allowed_client_mechanism = allowed_client_mechanism;
data.allowed_server_mechanism = allowed_server_mechanism;
data.address = g_dbus_server_get_client_address (server);
/* run the D-Bus client in a thread */
client_thread = g_thread_new ("gdbus-client-thread",
test_auth_client_thread_func,
&data);
g_dbus_server_start (server);
g_main_loop_run (loop);
g_dbus_server_stop (server);
g_thread_join (client_thread);
g_source_remove (timeout_id);
while (g_main_context_iteration (NULL, FALSE));
g_main_loop_unref (loop);
g_object_unref (server);
}
/* ---------------------------------------------------------------------------------------------------- */
static void
auth_client_external (void)
{
test_auth_mechanism ("EXTERNAL", NULL);
}
static void
auth_client_dbus_cookie_sha1 (void)
{
test_auth_mechanism ("DBUS_COOKIE_SHA1", NULL);
}
static void
auth_server_anonymous (void)
{
test_auth_mechanism (NULL, "ANONYMOUS");
}
static void
auth_server_external (void)
{
test_auth_mechanism (NULL, "EXTERNAL");
}
static void
auth_server_dbus_cookie_sha1 (void)
{
test_auth_mechanism (NULL, "DBUS_COOKIE_SHA1");
}
/* ---------------------------------------------------------------------------------------------------- */
static gchar *temp_dbus_keyrings_dir = NULL;
static void
temp_dbus_keyrings_setup (void)
{
GError *error = NULL;
g_assert (temp_dbus_keyrings_dir == NULL);
temp_dbus_keyrings_dir = g_dir_make_tmp ("gdbus-test-dbus-keyrings-XXXXXX", &error);
g_assert_no_error (error);
g_assert (temp_dbus_keyrings_dir != NULL);
g_setenv ("G_DBUS_COOKIE_SHA1_KEYRING_DIR", temp_dbus_keyrings_dir, TRUE);
g_setenv ("G_DBUS_COOKIE_SHA1_KEYRING_DIR_IGNORE_PERMISSION", "1", TRUE);
}
static void
temp_dbus_keyrings_teardown (void)
{
GDir *dir;
GError *error = NULL;
const gchar *name;
g_assert (temp_dbus_keyrings_dir != NULL);
dir = g_dir_open (temp_dbus_keyrings_dir, 0, &error);
g_assert_no_error (error);
g_assert (dir != NULL);
while ((name = g_dir_read_name (dir)) != NULL)
{
gchar *path = g_build_filename (temp_dbus_keyrings_dir, name, NULL);
g_assert (unlink (path) == 0);
g_free (path);
}
g_dir_close (dir);
g_assert (rmdir (temp_dbus_keyrings_dir) == 0);
g_free (temp_dbus_keyrings_dir);
temp_dbus_keyrings_dir = NULL;
g_unsetenv ("G_DBUS_COOKIE_SHA1_KEYRING_DIR");
g_unsetenv ("G_DBUS_COOKIE_SHA1_KEYRING_DIR_IGNORE_PERMISSION");
}
/* ---------------------------------------------------------------------------------------------------- */
int
main (int argc,
char *argv[])
{
gint ret;
setlocale (LC_ALL, "C");
temp_dbus_keyrings_setup ();
g_test_init (&argc, &argv, NULL);
g_test_add_func ("/gdbus/auth/client/EXTERNAL", auth_client_external);
g_test_add_func ("/gdbus/auth/client/DBUS_COOKIE_SHA1", auth_client_dbus_cookie_sha1);
g_test_add_func ("/gdbus/auth/server/ANONYMOUS", auth_server_anonymous);
g_test_add_func ("/gdbus/auth/server/EXTERNAL", auth_server_external);
g_test_add_func ("/gdbus/auth/server/DBUS_COOKIE_SHA1", auth_server_dbus_cookie_sha1);
/* TODO: we currently don't have tests for
*
* - DBUS_COOKIE_SHA1 timeouts (and clock changes etc)
* - interoperability with libdbus-1 implementations of authentication methods (both client and server)
*/
ret = g_test_run();
temp_dbus_keyrings_teardown ();
return ret;
}