/* * Copyright (C) 2020 Philip Withnall * Copyright (C) 2020 Richard Hughes * * SPDX-License-Identifier: LGPL-2.1+ */ #include typedef struct { GApplication *app; FwupdClient *client; GThread *main_thread; GThread *worker_thread; } FuThreadTestSelf; static gboolean fwupd_thread_test_exit_idle_cb(gpointer user_data) { FuThreadTestSelf *self = user_data; g_application_release(self->app); return G_SOURCE_REMOVE; } static gpointer fwupd_thread_test_thread_cb(gpointer user_data) { FuThreadTestSelf *self = user_data; g_autoptr(GError) error_local = NULL; g_autoptr(GMainContext) context = g_main_context_new(); g_autoptr(GMainContextPusher) pusher = g_main_context_pusher_new(context); g_assert(pusher != NULL); g_message("Calling fwupd_client_get_devices() in thread %p with main context %p", g_thread_self(), g_main_context_get_thread_default()); if (!fwupd_client_connect(self->client, NULL, &error_local)) g_warning("%s", error_local->message); g_idle_add(fwupd_thread_test_exit_idle_cb, self); return NULL; } static gboolean fwupd_thread_test_idle_cb(gpointer user_data) { FuThreadTestSelf *self = user_data; g_message("fwupd_thread_test_idle_cb() in thread %p with main context %p", g_thread_self(), g_main_context_get_thread_default()); self->worker_thread = g_thread_new("worker00", fwupd_thread_test_thread_cb, self); return G_SOURCE_REMOVE; } static void fwupd_thread_test_activate_cb(GApplication *app, gpointer user_data) { FuThreadTestSelf *self = user_data; g_application_hold(self->app); g_idle_add(fwupd_thread_test_idle_cb, self); } static void fwupd_thread_test_notify_cb(GObject *object, GParamSpec *pspec, gpointer user_data) { FuThreadTestSelf *self = user_data; g_message("fwupd_thread_test_notify_cb() in thread %p with main context %p", g_thread_self(), g_main_context_get_thread_default()); g_assert(g_thread_self() == self->main_thread); g_assert(g_main_context_get_thread_default() == NULL); } static gboolean fwupd_thread_test_has_system_bus(void) { g_autoptr(GDBusConnection) conn = NULL; conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL); return conn != NULL; } int main(void) { gint retval; g_autoptr(FwupdClient) client = fwupd_client_new(); g_autoptr(GApplication) app = g_application_new("org.fwupd.ContextTest", G_APPLICATION_FLAGS_NONE); g_autoptr(GThread) worker_thread = NULL; FuThreadTestSelf self = { .app = app, .client = client, .worker_thread = worker_thread, .main_thread = g_thread_self(), }; /* only some of the CI targets have a DBus daemon */ if (!fwupd_thread_test_has_system_bus()) { g_message("D-Bus system bus unavailable, skipping tests."); return 0; } g_message("Created FwupdClient in thread %p with main context %p", g_thread_self(), g_main_context_get_thread_default()); g_signal_connect(client, "notify::status", G_CALLBACK(fwupd_thread_test_notify_cb), &self); g_signal_connect(app, "activate", G_CALLBACK(fwupd_thread_test_activate_cb), &self); retval = g_application_run(app, 0, NULL); if (self.worker_thread != NULL) g_thread_join(g_steal_pointer(&self.worker_thread)); return retval; }