summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Withnall <philip@tecnocode.co.uk>2024-10-01 15:38:30 +0000
committerPhilip Withnall <philip@tecnocode.co.uk>2024-10-01 15:38:30 +0000
commit2b5d3b5831fb027ca041130bf91779ed7e5c9bf0 (patch)
tree2d5568b43b258d7f194570904854a595a540b405
parente14a393d27c2c5da8da41a196c7e125e0569ed22 (diff)
parent6b2cc430e0d8250e4f3e097998ed218b9bf12672 (diff)
Merge branch 'fake-document-portal-in-process' into 'main'
tests: Move fake-document-portal subprocess inside dbus-appinfo test See merge request GNOME/glib!4311
-rw-r--r--gio/tests/dbus-appinfo.c17
-rw-r--r--gio/tests/fake-document-portal.c213
-rw-r--r--gio/tests/fake-document-portal.h37
-rw-r--r--gio/tests/gdbus-sessionbus.c7
-rw-r--r--gio/tests/gdbus-sessionbus.h1
-rw-r--r--gio/tests/meson.build20
-rw-r--r--gio/tests/services/meson.build1
-rw-r--r--gio/tests/services/org.freedesktop.portal.Documents.service.in3
8 files changed, 241 insertions, 58 deletions
diff --git a/gio/tests/dbus-appinfo.c b/gio/tests/dbus-appinfo.c
index d84de7de9..80861fdd1 100644
--- a/gio/tests/dbus-appinfo.c
+++ b/gio/tests/dbus-appinfo.c
@@ -23,6 +23,7 @@
#include <gio/gdesktopappinfo.h>
#include "gdbus-sessionbus.h"
+#include "fake-document-portal.h"
static GDesktopAppInfo *appinfo;
static int current_state;
@@ -348,9 +349,14 @@ test_flatpak_doc_export (void)
GDesktopAppInfo *flatpak_appinfo;
GApplication *app;
int status;
+ GFakeDocumentPortalThread *thread = NULL;
g_test_summary ("Test that files launched via Flatpak apps are made available via the document portal.");
+ /* Run a fake-document-portal */
+ thread = g_fake_document_portal_thread_new (session_bus_get_address ());
+ g_fake_document_portal_thread_run (thread);
+
desktop_file = g_test_build_filename (G_TEST_DIST,
"org.gtk.test.dbusappinfo.flatpak.desktop",
NULL);
@@ -369,6 +375,8 @@ test_flatpak_doc_export (void)
g_object_unref (app);
g_object_unref (flatpak_appinfo);
+ g_fake_document_portal_thread_stop (thread);
+ g_clear_object (&thread);
}
static void
@@ -426,9 +434,14 @@ test_flatpak_missing_doc_export (void)
GDesktopAppInfo *flatpak_appinfo;
GApplication *app;
int status;
+ GFakeDocumentPortalThread *thread = NULL;
g_test_summary ("Test that files launched via Flatpak apps are made available via the document portal.");
+ /* Run a fake-document-portal */
+ thread = g_fake_document_portal_thread_new (session_bus_get_address ());
+ g_fake_document_portal_thread_run (thread);
+
desktop_file = g_test_build_filename (G_TEST_DIST,
"org.gtk.test.dbusappinfo.flatpak.desktop",
NULL);
@@ -447,12 +460,14 @@ test_flatpak_missing_doc_export (void)
g_object_unref (app);
g_object_unref (flatpak_appinfo);
g_free (desktop_file);
+ g_fake_document_portal_thread_stop (thread);
+ g_clear_object (&thread);
}
int
main (int argc, char **argv)
{
- g_test_init (&argc, &argv, NULL);
+ g_test_init (&argc, &argv, G_TEST_OPTION_ISOLATE_DIRS, NULL);
g_test_add_func ("/appinfo/dbusappinfo", test_dbus_appinfo);
g_test_add_func ("/appinfo/flatpak-doc-export", test_flatpak_doc_export);
diff --git a/gio/tests/fake-document-portal.c b/gio/tests/fake-document-portal.c
index 585dee58b..291e374d8 100644
--- a/gio/tests/fake-document-portal.c
+++ b/gio/tests/fake-document-portal.c
@@ -26,8 +26,56 @@
#include <gio/gio.h>
#include <gio/gunixfdlist.h>
+#include "fake-document-portal.h"
#include "fake-document-portal-generated.h"
+struct _GFakeDocumentPortalThread
+{
+ GObject parent_instance;
+
+ char *address; /* (not nullable) */
+ GCancellable *cancellable; /* (not nullable) (owned) */
+ GThread *thread; /* (not nullable) (owned) */
+ GCond cond; /* (mutex mutex) */
+ GMutex mutex;
+ gboolean ready; /* (mutex mutex) */
+};
+
+G_DEFINE_FINAL_TYPE (GFakeDocumentPortalThread, g_fake_document_portal_thread, G_TYPE_OBJECT)
+
+static void g_fake_document_portal_thread_finalize (GObject *object);
+
+static void
+g_fake_document_portal_thread_class_init (GFakeDocumentPortalThreadClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = g_fake_document_portal_thread_finalize;
+}
+
+static void
+g_fake_document_portal_thread_init (GFakeDocumentPortalThread *self)
+{
+ self->cancellable = g_cancellable_new ();
+ g_cond_init (&self->cond);
+ g_mutex_init (&self->mutex);
+}
+
+static void
+g_fake_document_portal_thread_finalize (GObject *object)
+{
+ GFakeDocumentPortalThread *self = G_FAKE_DOCUMENT_PORTAL_THREAD (object);
+
+ g_assert (self->thread == NULL); /* should already have been joined */
+
+ g_mutex_clear (&self->mutex);
+ g_cond_clear (&self->cond);
+ g_clear_object (&self->cancellable);
+ g_clear_pointer (&self->address, g_free);
+
+ G_OBJECT_CLASS (g_fake_document_portal_thread_parent_class)->finalize (object);
+}
+
static gboolean
on_handle_get_mount_point (FakeDocuments *object,
GDBusMethodInvocation *invocation,
@@ -76,13 +124,66 @@ on_handle_add_full (FakeDocuments *object,
}
static void
-on_bus_acquired (GDBusConnection *connection,
- const gchar *name,
- gpointer user_data)
+on_name_acquired (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ GFakeDocumentPortalThread *self = G_FAKE_DOCUMENT_PORTAL_THREAD (user_data);
+
+ g_test_message ("Acquired the name %s", name);
+
+ g_mutex_lock (&self->mutex);
+ self->ready = TRUE;
+ g_cond_signal (&self->cond);
+ g_mutex_unlock (&self->mutex);
+}
+
+static void
+on_name_lost (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ g_test_message ("Lost the name %s", name);
+}
+
+static gboolean
+cancelled_cb (GCancellable *cancellable,
+ gpointer user_data)
{
- FakeDocuments *interface;
- GError *error = NULL;
+ g_test_message ("fake-document-portal cancelled");
+ return G_SOURCE_CONTINUE;
+}
+
+static gpointer
+fake_document_portal_thread_cb (gpointer user_data)
+{
+ GFakeDocumentPortalThread *self = G_FAKE_DOCUMENT_PORTAL_THREAD (user_data);
+ GMainContext *context = NULL;
+ GDBusConnection *connection = NULL;
+ GSource *source = NULL;
+ guint id;
+ FakeDocuments *interface = NULL;
+ GError *local_error = NULL;
+ context = g_main_context_new ();
+ g_main_context_push_thread_default (context);
+
+ connection = g_dbus_connection_new_for_address_sync (self->address,
+ G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
+ G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
+ NULL,
+ self->cancellable,
+ &local_error);
+ g_assert_no_error (local_error);
+
+ /* Listen for cancellation. The source will wake up the context iteration
+ * which can then re-check its exit condition below. */
+ source = g_cancellable_source_new (self->cancellable);
+ g_source_set_callback (source, G_SOURCE_FUNC (cancelled_cb), NULL, NULL);
+ g_source_attach (source, context);
+ g_source_unref (source);
+
+ /* Set up the interface */
g_test_message ("Acquired a message bus connection");
interface = fake_documents_skeleton_new ();
@@ -98,51 +199,81 @@ on_bus_acquired (GDBusConnection *connection,
g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (interface),
connection,
"/org/freedesktop/portal/documents",
- &error);
- g_assert_no_error (error);
-}
+ &local_error);
+ g_assert_no_error (local_error);
-static void
-on_name_acquired (GDBusConnection *connection,
- const gchar *name,
- gpointer user_data)
-{
- g_test_message ("Acquired the name %s", name);
+ /* Own the portal name */
+ id = g_bus_own_name_on_connection (connection,
+ "org.freedesktop.portal.Documents",
+ G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
+ G_BUS_NAME_OWNER_FLAGS_REPLACE,
+ on_name_acquired,
+ on_name_lost,
+ self,
+ NULL);
+
+ while (!g_cancellable_is_cancelled (self->cancellable))
+ g_main_context_iteration (context, TRUE);
+
+ g_bus_unown_name (id);
+ g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (interface));
+ g_clear_object (&interface);
+ g_clear_object (&connection);
+ g_main_context_pop_thread_default (context);
+ g_clear_pointer (&context, g_main_context_unref);
+
+ return NULL;
}
-static void
-on_name_lost (GDBusConnection *connection,
- const gchar *name,
- gpointer user_data)
+/*
+ * Create a new #GFakeDocumentPortalThread. The thread isn’t started until
+ * g_fake_document_portal_thread_run() is called on it.
+ *
+ * Returns: (transfer full): the new fake document portal wrapper
+ */
+GFakeDocumentPortalThread *
+g_fake_document_portal_thread_new (const char *address)
{
- g_test_message ("Lost the name %s", name);
+ GFakeDocumentPortalThread *self = g_object_new (G_TYPE_FAKE_DOCUMENT_PORTAL_THREAD, NULL);
+ self->address = g_strdup (address);
+ return g_steal_pointer (&self);
}
-
-gint
-main (gint argc, gchar *argv[])
+/*
+ * Start a worker thread which will run a fake
+ * `org.freedesktop.portal.Documents` portal on the bus at @address. This is
+ * intended to be used with #GTestDBus to mock up a portal from within a unit
+ * test process, rather than relying on D-Bus activation of a mock portal
+ * subprocess.
+ *
+ * It blocks until the thread has owned its D-Bus name and is ready to handle
+ * requests.
+ */
+void
+g_fake_document_portal_thread_run (GFakeDocumentPortalThread *self)
{
- GMainLoop *loop;
- guint id;
-
- g_log_writer_default_set_use_stderr (TRUE);
-
- loop = g_main_loop_new (NULL, FALSE);
+ g_return_if_fail (G_IS_FAKE_DOCUMENT_PORTAL_THREAD (self));
+ g_return_if_fail (self->thread == NULL);
- id = g_bus_own_name (G_BUS_TYPE_SESSION,
- "org.freedesktop.portal.Documents",
- G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
- G_BUS_NAME_OWNER_FLAGS_REPLACE,
- on_bus_acquired,
- on_name_acquired,
- on_name_lost,
- loop,
- NULL);
+ self->thread = g_thread_new ("fake-document-portal", fake_document_portal_thread_cb, self);
- g_main_loop_run (loop);
+ /* Block until the thread is ready. */
+ g_mutex_lock (&self->mutex);
+ while (!self->ready)
+ g_cond_wait (&self->cond, &self->mutex);
+ g_mutex_unlock (&self->mutex);
+}
- g_bus_unown_name (id);
- g_main_loop_unref (loop);
+/* Stop and join a worker thread started with fake_document_portal_thread_run().
+ * Blocks until the thread has stopped and joined.
+ *
+ * Once this has been called, it’s safe to drop the final reference on @self. */
+void
+g_fake_document_portal_thread_stop (GFakeDocumentPortalThread *self)
+{
+ g_return_if_fail (G_IS_FAKE_DOCUMENT_PORTAL_THREAD (self));
+ g_return_if_fail (self->thread != NULL);
- return 0;
+ g_cancellable_cancel (self->cancellable);
+ g_thread_join (g_steal_pointer (&self->thread));
}
diff --git a/gio/tests/fake-document-portal.h b/gio/tests/fake-document-portal.h
new file mode 100644
index 000000000..f1845b563
--- /dev/null
+++ b/gio/tests/fake-document-portal.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2024 GNOME Foundation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ *
+ * 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/>.
+ */
+
+#ifndef __FAKE_DOCUMENT_PORTAL_H__
+#define __FAKE_DOCUMENT_PORTAL_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_FAKE_DOCUMENT_PORTAL_THREAD (g_fake_document_portal_thread_get_type ())
+G_DECLARE_FINAL_TYPE (GFakeDocumentPortalThread, g_fake_document_portal_thread, G, FAKE_DOCUMENT_PORTAL_THREAD, GObject)
+
+GFakeDocumentPortalThread *g_fake_document_portal_thread_new (const char *address);
+void g_fake_document_portal_thread_run (GFakeDocumentPortalThread *self);
+void g_fake_document_portal_thread_stop (GFakeDocumentPortalThread *self);
+
+G_END_DECLS
+
+#endif /* __FAKE_DOCUMENT_PORTAL_H__ */
diff --git a/gio/tests/gdbus-sessionbus.c b/gio/tests/gdbus-sessionbus.c
index 09d163969..f4dbb4ff9 100644
--- a/gio/tests/gdbus-sessionbus.c
+++ b/gio/tests/gdbus-sessionbus.c
@@ -71,3 +71,10 @@ session_bus_run (void)
return ret;
}
+
+const char *
+session_bus_get_address (void)
+{
+ g_assert (singleton != NULL);
+ return g_test_dbus_get_bus_address (singleton);
+}
diff --git a/gio/tests/gdbus-sessionbus.h b/gio/tests/gdbus-sessionbus.h
index bd6f2a2ad..9fa80336f 100644
--- a/gio/tests/gdbus-sessionbus.h
+++ b/gio/tests/gdbus-sessionbus.h
@@ -31,6 +31,7 @@ void session_bus_up (void);
void session_bus_stop (void);
void session_bus_down (void);
gint session_bus_run (void);
+const char *session_bus_get_address (void);
G_END_DECLS
diff --git a/gio/tests/meson.build b/gio/tests/meson.build
index 2fd1a2a7b..3e4e1e847 100644
--- a/gio/tests/meson.build
+++ b/gio/tests/meson.build
@@ -544,15 +544,6 @@ if host_machine.system() != 'windows'
},
}
- if not glib_have_cocoa
- gio_tests += {
- 'dbus-appinfo' : {
- 'extra_sources' : extra_sources,
- 'extra_programs' : ['fake-document-portal'],
- },
- }
- endif
-
fake_document_portal_generated = custom_target('fake-document-portal-generated',
input : ['../org.freedesktop.portal.Documents.xml'],
output : ['fake-document-portal-generated.h',
@@ -566,10 +557,15 @@ if host_machine.system() != 'windows'
'--c-namespace', 'Fake',
'@INPUT@'])
+ if not glib_have_cocoa
+ gio_tests += {
+ 'dbus-appinfo' : {
+ 'extra_sources' : [extra_sources, 'fake-document-portal.c', fake_document_portal_generated],
+ },
+ }
+ endif
+
test_extra_programs += {
- 'fake-document-portal' : {
- 'extra_sources': fake_document_portal_generated,
- },
'fake-service-name' : {}
}
endif # have_dbus_daemon
diff --git a/gio/tests/services/meson.build b/gio/tests/services/meson.build
index b6a901bc5..27e8948f4 100644
--- a/gio/tests/services/meson.build
+++ b/gio/tests/services/meson.build
@@ -1,5 +1,4 @@
dbus_service_files = [
- 'org.freedesktop.portal.Documents.service',
'org.gtk.GDBus.FakeService.service'
]
diff --git a/gio/tests/services/org.freedesktop.portal.Documents.service.in b/gio/tests/services/org.freedesktop.portal.Documents.service.in
deleted file mode 100644
index 2769ff7b6..000000000
--- a/gio/tests/services/org.freedesktop.portal.Documents.service.in
+++ /dev/null
@@ -1,3 +0,0 @@
-[D-BUS Service]
-Name=org.freedesktop.portal.Documents
-Exec=@installed_tests_dir@/fake-document-portal