mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-11 15:06:14 +01:00
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
This commit is contained in:
commit
2b5d3b5831
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
FakeDocuments *interface;
|
||||
GError *error = NULL;
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
static void
|
||||
on_name_lost (GDBusConnection *connection,
|
||||
const gchar *name,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_test_message ("Lost the name %s", name);
|
||||
}
|
||||
|
||||
|
||||
gint
|
||||
main (gint argc, gchar *argv[])
|
||||
{
|
||||
GMainLoop *loop;
|
||||
guint id;
|
||||
|
||||
g_log_writer_default_set_use_stderr (TRUE);
|
||||
|
||||
loop = g_main_loop_new (NULL, FALSE);
|
||||
|
||||
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);
|
||||
|
||||
g_main_loop_run (loop);
|
||||
while (!g_cancellable_is_cancelled (self->cancellable))
|
||||
g_main_context_iteration (context, TRUE);
|
||||
|
||||
g_bus_unown_name (id);
|
||||
g_main_loop_unref (loop);
|
||||
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 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
GFakeDocumentPortalThread *self = g_object_new (G_TYPE_FAKE_DOCUMENT_PORTAL_THREAD, NULL);
|
||||
self->address = g_strdup (address);
|
||||
return g_steal_pointer (&self);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
g_return_if_fail (G_IS_FAKE_DOCUMENT_PORTAL_THREAD (self));
|
||||
g_return_if_fail (self->thread == NULL);
|
||||
|
||||
self->thread = g_thread_new ("fake-document-portal", fake_document_portal_thread_cb, self);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
g_cancellable_cancel (self->cancellable);
|
||||
g_thread_join (g_steal_pointer (&self->thread));
|
||||
}
|
||||
|
37
gio/tests/fake-document-portal.h
Normal file
37
gio/tests/fake-document-portal.h
Normal file
@ -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__ */
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -1,5 +1,4 @@
|
||||
dbus_service_files = [
|
||||
'org.freedesktop.portal.Documents.service',
|
||||
'org.gtk.GDBus.FakeService.service'
|
||||
]
|
||||
|
||||
|
@ -1,3 +0,0 @@
|
||||
[D-BUS Service]
|
||||
Name=org.freedesktop.portal.Documents
|
||||
Exec=@installed_tests_dir@/fake-document-portal
|
Loading…
Reference in New Issue
Block a user