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 <gio/gdesktopappinfo.h>
|
||||||
|
|
||||||
#include "gdbus-sessionbus.h"
|
#include "gdbus-sessionbus.h"
|
||||||
|
#include "fake-document-portal.h"
|
||||||
|
|
||||||
static GDesktopAppInfo *appinfo;
|
static GDesktopAppInfo *appinfo;
|
||||||
static int current_state;
|
static int current_state;
|
||||||
@ -348,9 +349,14 @@ test_flatpak_doc_export (void)
|
|||||||
GDesktopAppInfo *flatpak_appinfo;
|
GDesktopAppInfo *flatpak_appinfo;
|
||||||
GApplication *app;
|
GApplication *app;
|
||||||
int status;
|
int status;
|
||||||
|
GFakeDocumentPortalThread *thread = NULL;
|
||||||
|
|
||||||
g_test_summary ("Test that files launched via Flatpak apps are made available via the document portal.");
|
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,
|
desktop_file = g_test_build_filename (G_TEST_DIST,
|
||||||
"org.gtk.test.dbusappinfo.flatpak.desktop",
|
"org.gtk.test.dbusappinfo.flatpak.desktop",
|
||||||
NULL);
|
NULL);
|
||||||
@ -369,6 +375,8 @@ test_flatpak_doc_export (void)
|
|||||||
|
|
||||||
g_object_unref (app);
|
g_object_unref (app);
|
||||||
g_object_unref (flatpak_appinfo);
|
g_object_unref (flatpak_appinfo);
|
||||||
|
g_fake_document_portal_thread_stop (thread);
|
||||||
|
g_clear_object (&thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -426,9 +434,14 @@ test_flatpak_missing_doc_export (void)
|
|||||||
GDesktopAppInfo *flatpak_appinfo;
|
GDesktopAppInfo *flatpak_appinfo;
|
||||||
GApplication *app;
|
GApplication *app;
|
||||||
int status;
|
int status;
|
||||||
|
GFakeDocumentPortalThread *thread = NULL;
|
||||||
|
|
||||||
g_test_summary ("Test that files launched via Flatpak apps are made available via the document portal.");
|
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,
|
desktop_file = g_test_build_filename (G_TEST_DIST,
|
||||||
"org.gtk.test.dbusappinfo.flatpak.desktop",
|
"org.gtk.test.dbusappinfo.flatpak.desktop",
|
||||||
NULL);
|
NULL);
|
||||||
@ -447,12 +460,14 @@ test_flatpak_missing_doc_export (void)
|
|||||||
g_object_unref (app);
|
g_object_unref (app);
|
||||||
g_object_unref (flatpak_appinfo);
|
g_object_unref (flatpak_appinfo);
|
||||||
g_free (desktop_file);
|
g_free (desktop_file);
|
||||||
|
g_fake_document_portal_thread_stop (thread);
|
||||||
|
g_clear_object (&thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char **argv)
|
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/dbusappinfo", test_dbus_appinfo);
|
||||||
g_test_add_func ("/appinfo/flatpak-doc-export", test_flatpak_doc_export);
|
g_test_add_func ("/appinfo/flatpak-doc-export", test_flatpak_doc_export);
|
||||||
|
@ -26,8 +26,56 @@
|
|||||||
#include <gio/gio.h>
|
#include <gio/gio.h>
|
||||||
#include <gio/gunixfdlist.h>
|
#include <gio/gunixfdlist.h>
|
||||||
|
|
||||||
|
#include "fake-document-portal.h"
|
||||||
#include "fake-document-portal-generated.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
|
static gboolean
|
||||||
on_handle_get_mount_point (FakeDocuments *object,
|
on_handle_get_mount_point (FakeDocuments *object,
|
||||||
GDBusMethodInvocation *invocation,
|
GDBusMethodInvocation *invocation,
|
||||||
@ -76,13 +124,66 @@ on_handle_add_full (FakeDocuments *object,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_bus_acquired (GDBusConnection *connection,
|
on_name_acquired (GDBusConnection *connection,
|
||||||
const gchar *name,
|
const gchar *name,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
FakeDocuments *interface;
|
GFakeDocumentPortalThread *self = G_FAKE_DOCUMENT_PORTAL_THREAD (user_data);
|
||||||
GError *error = NULL;
|
|
||||||
|
|
||||||
|
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");
|
g_test_message ("Acquired a message bus connection");
|
||||||
|
|
||||||
interface = fake_documents_skeleton_new ();
|
interface = fake_documents_skeleton_new ();
|
||||||
@ -98,51 +199,81 @@ on_bus_acquired (GDBusConnection *connection,
|
|||||||
g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (interface),
|
g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (interface),
|
||||||
connection,
|
connection,
|
||||||
"/org/freedesktop/portal/documents",
|
"/org/freedesktop/portal/documents",
|
||||||
&error);
|
&local_error);
|
||||||
g_assert_no_error (error);
|
g_assert_no_error (local_error);
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
/* Own the portal name */
|
||||||
on_name_acquired (GDBusConnection *connection,
|
id = g_bus_own_name_on_connection (connection,
|
||||||
const gchar *name,
|
"org.freedesktop.portal.Documents",
|
||||||
gpointer user_data)
|
G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
|
||||||
{
|
G_BUS_NAME_OWNER_FLAGS_REPLACE,
|
||||||
g_test_message ("Acquired the name %s", name);
|
on_name_acquired,
|
||||||
}
|
on_name_lost,
|
||||||
|
self,
|
||||||
|
NULL);
|
||||||
|
|
||||||
static void
|
while (!g_cancellable_is_cancelled (self->cancellable))
|
||||||
on_name_lost (GDBusConnection *connection,
|
g_main_context_iteration (context, TRUE);
|
||||||
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);
|
|
||||||
|
|
||||||
g_bus_unown_name (id);
|
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;
|
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_stop (void);
|
||||||
void session_bus_down (void);
|
void session_bus_down (void);
|
||||||
gint session_bus_run (void);
|
gint session_bus_run (void);
|
||||||
|
const char *session_bus_get_address (void);
|
||||||
|
|
||||||
G_END_DECLS
|
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',
|
fake_document_portal_generated = custom_target('fake-document-portal-generated',
|
||||||
input : ['../org.freedesktop.portal.Documents.xml'],
|
input : ['../org.freedesktop.portal.Documents.xml'],
|
||||||
output : ['fake-document-portal-generated.h',
|
output : ['fake-document-portal-generated.h',
|
||||||
@ -566,10 +557,15 @@ if host_machine.system() != 'windows'
|
|||||||
'--c-namespace', 'Fake',
|
'--c-namespace', 'Fake',
|
||||||
'@INPUT@'])
|
'@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 += {
|
test_extra_programs += {
|
||||||
'fake-document-portal' : {
|
|
||||||
'extra_sources': fake_document_portal_generated,
|
|
||||||
},
|
|
||||||
'fake-service-name' : {}
|
'fake-service-name' : {}
|
||||||
}
|
}
|
||||||
endif # have_dbus_daemon
|
endif # have_dbus_daemon
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
dbus_service_files = [
|
dbus_service_files = [
|
||||||
'org.freedesktop.portal.Documents.service',
|
|
||||||
'org.gtk.GDBus.FakeService.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