1
0
Fork 0
gnome-software/plugins/flatpak/gs-self-test.c
Daniel Baumann 68ee05b3fd
Adding upstream version 48.2.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-22 21:00:23 +02:00

2011 lines
78 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
* vi:set noexpandtab tabstop=8 shiftwidth=8:
*
* Copyright (C) 2013-2018 Richard Hughes <richard@hughsie.com>
* Copyright (C) 2017 Kalev Lember <klember@redhat.com>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "config.h"
#include <glib/gstdio.h>
#include "gnome-software-private.h"
#include "gs-flatpak-app.h"
#include "gs-test.h"
const gchar * const allowlist[] = {
"appstream",
"flatpak",
"icons",
NULL
};
static gboolean
gs_flatpak_test_write_repo_file (const gchar *fn, const gchar *testdir, GFile **file_out, GError **error)
{
g_autofree gchar *testdir_repourl = NULL;
g_autoptr(GString) str = g_string_new (NULL);
g_autofree gchar *path = NULL;
/* create file */
testdir_repourl = g_strdup_printf ("file://%s/repo", testdir);
g_string_append (str, "[Flatpak Repo]\n");
g_string_append (str, "Title=foo-bar\n");
g_string_append (str, "Comment=Longer one line comment\n");
g_string_append (str, "Description=Longer multiline comment that "
"does into detail.\n");
g_string_append (str, "DefaultBranch=master\n");
g_string_append_printf (str, "Url=%s\n", testdir_repourl);
g_string_append (str, "Homepage=http://foo.bar\n");
path = g_build_filename (g_getenv ("GS_SELF_TEST_FLATPAK_DATADIR"), fn, NULL);
*file_out = g_file_new_for_path (path);
return g_file_set_contents (path, str->str, -1, error);
}
static gboolean
gs_flatpak_test_write_ref_file (const gchar *filename, const gchar *url, const gchar *runtimerepo, GFile **file_out, GError **error)
{
g_autoptr(GString) str = g_string_new (NULL);
g_autofree gchar *path = NULL;
g_return_val_if_fail (filename != NULL, FALSE);
g_return_val_if_fail (url != NULL, FALSE);
g_return_val_if_fail (runtimerepo != NULL, FALSE);
g_string_append (str, "[Flatpak Ref]\n");
g_string_append (str, "Title=Chiron\n");
g_string_append (str, "Name=org.test.Chiron\n");
g_string_append (str, "Branch=master\n");
g_string_append_printf (str, "Url=%s\n", url);
g_string_append (str, "IsRuntime=false\n");
g_string_append (str, "Comment=Single line synopsis\n");
g_string_append (str, "Description=A Testing Application\n");
g_string_append (str, "Icon=https://getfedora.org/static/images/fedora-logotext.png\n");
g_string_append_printf (str, "RuntimeRepo=%s\n", runtimerepo);
path = g_build_filename (g_getenv ("GS_SELF_TEST_FLATPAK_DATADIR"), filename, NULL);
*file_out = g_file_new_for_path (path);
return g_file_set_contents (path, str->str, -1, error);
}
/* create duplicate file as if downloaded in firefox */
static void
gs_plugins_flatpak_repo_non_ascii_func (GsPluginLoader *plugin_loader)
{
const gchar *fn = "example (1)….flatpakrepo";
gboolean ret;
g_autofree gchar *testdir = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(GFile) file = NULL;
g_autoptr(GsApp) app = NULL;
g_autoptr(GsPluginJob) plugin_job = NULL;
/* get a resolvable */
testdir = gs_test_get_filename (TESTDATADIR, "app-with-runtime");
if (testdir == NULL)
return;
ret = gs_flatpak_test_write_repo_file (fn, testdir, &file, &error);
g_assert_no_error (error);
g_assert_true (ret);
plugin_job = gs_plugin_job_file_to_app_new (file, GS_PLUGIN_FILE_TO_APP_FLAGS_NONE);
app = gs_plugin_loader_job_process_app (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_true (app != NULL);
g_assert_cmpstr (gs_app_get_unique_id (app), ==, "user/*/*/example__1____/master");
}
static void
gs_plugins_flatpak_repo_func (GsPluginLoader *plugin_loader)
{
const gchar *group_name = "remote \"example\"";
const gchar *root = NULL;
const gchar *fn = "example.flatpakrepo";
gboolean ret;
g_autofree gchar *config_fn = NULL;
g_autofree gchar *remote_url = NULL;
g_autofree gchar *testdir = NULL;
g_autofree gchar *testdir_repourl = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(GFile) file = NULL;
g_autoptr(GKeyFile) kf = NULL;
g_autoptr(GsApp) app2 = NULL;
g_autoptr(GsApp) app = NULL;
g_autoptr(GsPluginJob) plugin_job = NULL;
g_autoptr(GIcon) icon = NULL;
g_autoptr(GsPlugin) management_plugin = NULL;
/* no flatpak, abort */
if (!gs_plugin_loader_get_enabled (plugin_loader, "flatpak"))
return;
/* get a resolvable */
testdir = gs_test_get_filename (TESTDATADIR, "app-with-runtime");
if (testdir == NULL)
return;
testdir_repourl = g_strdup_printf ("file://%s/repo", testdir);
/* create file */
ret = gs_flatpak_test_write_repo_file (fn, testdir, &file, &error);
g_assert_no_error (error);
g_assert_true (ret);
/* load local file */
plugin_job = gs_plugin_job_file_to_app_new (file, GS_PLUGIN_FILE_TO_APP_FLAGS_NONE);
app = gs_plugin_loader_job_process_app (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_true (app != NULL);
g_assert_cmpint (gs_app_get_kind (app), ==, AS_COMPONENT_KIND_REPOSITORY);
g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_AVAILABLE_LOCAL);
g_assert_cmpstr (gs_app_get_id (app), ==, "example");
management_plugin = gs_app_dup_management_plugin (app);
g_assert_nonnull (management_plugin);
g_assert_cmpstr (gs_plugin_get_name (management_plugin), ==, "flatpak");
g_assert_cmpstr (gs_app_get_origin_hostname (app), ==, "localhost");
g_assert_cmpstr (gs_app_get_url (app, AS_URL_KIND_HOMEPAGE), ==, "http://foo.bar");
g_assert_cmpstr (gs_app_get_name (app), ==, "foo-bar");
g_assert_cmpstr (gs_app_get_summary (app), ==, "Longer one line comment");
g_assert_cmpstr (gs_app_get_description (app), ==,
"Longer multiline comment that does into detail.");
g_assert_true (gs_app_get_local_file (app) != NULL);
/* The app has an icon, but cannot be found since it is not installed */
g_assert_true (gs_app_has_icons (app));
icon = gs_app_get_icon_for_size (app, 64, 1, NULL);
g_assert_null (icon);
/* now install the remote */
g_object_unref (plugin_job);
plugin_job = gs_plugin_job_manage_repository_new (app, GS_PLUGIN_MANAGE_REPOSITORY_FLAGS_INSTALL);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_true (ret);
g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_INSTALLED);
/* check config file was updated */
root = g_getenv ("GS_SELF_TEST_FLATPAK_DATADIR");
config_fn = g_build_filename (root, "flatpak", "repo", "config", NULL);
kf = g_key_file_new ();
ret = g_key_file_load_from_file (kf, config_fn, 0, &error);
g_assert_no_error (error);
g_assert_true (ret);
g_assert_true (g_key_file_has_group (kf, "core"));
g_assert_true (g_key_file_has_group (kf, group_name));
g_assert_true (!g_key_file_get_boolean (kf, group_name, "gpg-verify", NULL));
/* check the URL was unmangled */
remote_url = g_key_file_get_string (kf, group_name, "url", &error);
g_assert_no_error (error);
g_assert_cmpstr (remote_url, ==, testdir_repourl);
/* try again, check state is correct */
g_object_unref (plugin_job);
plugin_job = gs_plugin_job_file_to_app_new (file, GS_PLUGIN_FILE_TO_APP_FLAGS_NONE);
app2 = gs_plugin_loader_job_process_app (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_true (app2 != NULL);
g_assert_cmpint (gs_app_get_state (app2), ==, GS_APP_STATE_INSTALLED);
/* disable repo */
g_object_unref (plugin_job);
plugin_job = gs_plugin_job_manage_repository_new (app, GS_PLUGIN_MANAGE_REPOSITORY_FLAGS_DISABLE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_true (ret);
g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_AVAILABLE);
g_assert_cmpint (gs_app_get_progress (app), ==, GS_APP_PROGRESS_UNKNOWN);
/* enable repo */
g_object_unref (plugin_job);
plugin_job = gs_plugin_job_manage_repository_new (app, GS_PLUGIN_MANAGE_REPOSITORY_FLAGS_ENABLE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_true (ret);
g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_INSTALLED);
g_assert_cmpint (gs_app_get_progress (app), ==, GS_APP_PROGRESS_UNKNOWN);
/* remove it */
g_object_unref (plugin_job);
plugin_job = gs_plugin_job_manage_repository_new (app, GS_PLUGIN_MANAGE_REPOSITORY_FLAGS_REMOVE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_true (ret);
g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_UNAVAILABLE);
g_assert_cmpint (gs_app_get_progress (app), ==, GS_APP_PROGRESS_UNKNOWN);
}
static void
progress_notify_cb (GObject *obj, GParamSpec *pspec, gpointer user_data)
{
gboolean *seen_unknown = user_data;
GsApp *app = GS_APP (obj);
if (gs_app_get_progress (app) == GS_APP_PROGRESS_UNKNOWN)
*seen_unknown = TRUE;
}
static void
gs_plugins_flatpak_app_with_runtime_func (GsPluginLoader *plugin_loader)
{
GsApp *app;
GsApp *runtime;
const gchar *root;
gboolean ret;
gint kf_remote_repo_version;
g_autofree gchar *changed_fn = NULL;
g_autofree gchar *config_fn = NULL;
g_autofree gchar *desktop_fn = NULL;
g_autofree gchar *kf_remote_url = NULL;
g_autofree gchar *metadata_fn = NULL;
g_autofree gchar *repodir_fn = NULL;
g_autofree gchar *runtime_fn = NULL;
g_autofree gchar *testdir = NULL;
g_autofree gchar *testdir_repourl = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(GKeyFile) kf1 = g_key_file_new ();
g_autoptr(GKeyFile) kf2 = g_key_file_new ();
g_autoptr(GsApp) app_source = NULL;
g_autoptr(GsAppList) list_all = NULL;
g_autoptr(GsAppList) list = NULL;
g_autoptr(GsAppList) sources = NULL;
g_autoptr(GsAppList) runtime_list = NULL;
g_autoptr(GsPluginJob) plugin_job = NULL;
gulong signal_id;
gboolean seen_unknown;
GsPlugin *plugin;
g_autoptr(GsAppQuery) query = NULL;
const gchar *keywords[2] = { NULL, };
/* drop all caches */
gs_utils_rmtree (g_getenv ("GS_SELF_TEST_CACHEDIR"), NULL);
gs_test_reinitialise_plugin_loader (plugin_loader, allowlist, NULL);
/* no flatpak, abort */
if (!gs_plugin_loader_get_enabled (plugin_loader, "flatpak"))
return;
/* no files to use */
repodir_fn = gs_test_get_filename (TESTDATADIR, "app-with-runtime/repo");
if (repodir_fn == NULL ||
!g_file_test (repodir_fn, G_FILE_TEST_EXISTS)) {
g_test_skip ("no flatpak test repo");
return;
}
/* check changed file exists */
root = g_getenv ("GS_SELF_TEST_FLATPAK_DATADIR");
changed_fn = g_build_filename (root, "flatpak", ".changed", NULL);
g_assert_true (g_file_test (changed_fn, G_FILE_TEST_IS_REGULAR));
/* check repo is set up */
config_fn = g_build_filename (root, "flatpak", "repo", "config", NULL);
ret = g_key_file_load_from_file (kf1, config_fn, G_KEY_FILE_NONE, &error);
g_assert_no_error (error);
g_assert_true (ret);
kf_remote_repo_version = g_key_file_get_integer (kf1, "core", "repo_version", &error);
g_assert_no_error (error);
g_assert_cmpint (kf_remote_repo_version, ==, 1);
/* add a remote */
app_source = gs_flatpak_app_new ("test");
testdir = gs_test_get_filename (TESTDATADIR, "app-with-runtime");
if (testdir == NULL)
return;
testdir_repourl = g_strdup_printf ("file://%s/repo", testdir);
gs_app_set_kind (app_source, AS_COMPONENT_KIND_REPOSITORY);
plugin = gs_plugin_loader_find_plugin (plugin_loader, "flatpak");
gs_app_set_management_plugin (app_source, plugin);
gs_app_set_state (app_source, GS_APP_STATE_AVAILABLE);
gs_flatpak_app_set_repo_url (app_source, testdir_repourl);
plugin_job = gs_plugin_job_manage_repository_new (app_source, GS_PLUGIN_MANAGE_REPOSITORY_FLAGS_INSTALL);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_true (ret);
g_assert_cmpint (gs_app_get_state (app_source), ==, GS_APP_STATE_INSTALLED);
/* check remote was set up */
ret = g_key_file_load_from_file (kf2, config_fn, G_KEY_FILE_NONE, &error);
g_assert_no_error (error);
g_assert_true (ret);
kf_remote_url = g_key_file_get_string (kf2, "remote \"test\"", "url", &error);
g_assert_no_error (error);
g_assert_cmpstr (kf_remote_url, !=, NULL);
/* check the source now exists */
g_object_unref (plugin_job);
query = gs_app_query_new ("is-source", GS_APP_QUERY_TRISTATE_TRUE, NULL);
plugin_job = gs_plugin_job_list_apps_new (query, GS_PLUGIN_LIST_APPS_FLAGS_NONE);
g_clear_object (&query);
sources = gs_plugin_loader_job_process (plugin_loader, plugin_job, NULL, &error);
g_assert_no_error (error);
g_assert_true (sources != NULL);
g_assert_cmpint (gs_app_list_length (sources), ==, 1);
app = gs_app_list_index (sources, 0);
g_assert_cmpstr (gs_app_get_id (app), ==, "test");
g_assert_cmpint (gs_app_get_kind (app), ==, AS_COMPONENT_KIND_REPOSITORY);
/* refresh the appstream metadata */
g_object_unref (plugin_job);
plugin_job = gs_plugin_job_refresh_metadata_new (G_MAXUINT64,
GS_PLUGIN_REFRESH_METADATA_FLAGS_NONE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
g_assert_no_error (error);
g_assert_true (ret);
/* all the apps should have the flatpak keyword */
g_object_unref (plugin_job);
keywords[0] = "flatpak";
query = gs_app_query_new ("keywords", keywords,
"refine-flags", GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON,
"dedupe-flags", GS_PLUGIN_JOB_DEDUPE_FLAGS_DEFAULT,
"sort-func", gs_utils_app_sort_match_value,
NULL);
plugin_job = gs_plugin_job_list_apps_new (query, GS_PLUGIN_LIST_APPS_FLAGS_NONE);
g_clear_object (&query);
list_all = gs_plugin_loader_job_process (plugin_loader, plugin_job, NULL, &error);
g_assert_no_error (error);
g_assert_true (list_all != NULL);
g_assert_cmpint (gs_app_list_length (list_all), ==, 2);
/* find available application */
g_object_unref (plugin_job);
keywords[0] = "Bingo";
query = gs_app_query_new ("keywords", keywords,
"refine-flags", GS_PLUGIN_REFINE_FLAGS_REQUIRE_ORIGIN_HOSTNAME |
GS_PLUGIN_REFINE_FLAGS_REQUIRE_PERMISSIONS |
GS_PLUGIN_REFINE_FLAGS_REQUIRE_VERSION |
GS_PLUGIN_REFINE_FLAGS_REQUIRE_KUDOS |
GS_PLUGIN_REFINE_FLAGS_REQUIRE_RUNTIME |
GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON,
"dedupe-flags", GS_PLUGIN_JOB_DEDUPE_FLAGS_DEFAULT,
"sort-func", gs_utils_app_sort_match_value,
NULL);
plugin_job = gs_plugin_job_list_apps_new (query, GS_PLUGIN_LIST_APPS_FLAGS_NONE);
g_clear_object (&query);
list = gs_plugin_loader_job_process (plugin_loader, plugin_job, NULL, &error);
g_assert_no_error (error);
g_assert_true (list != NULL);
/* make sure there is one entry, the flatpak app */
g_assert_cmpint (gs_app_list_length (list), ==, 1);
app = gs_app_list_index (list, 0);
g_assert_cmpstr (gs_app_get_id (app), ==, "org.test.Chiron");
g_assert_cmpint (gs_app_get_kind (app), ==, AS_COMPONENT_KIND_DESKTOP_APP);
g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_AVAILABLE);
g_assert_cmpint ((gint64) gs_app_get_kudos (app), ==,
GS_APP_KUDO_MY_LANGUAGE |
GS_APP_KUDO_HAS_KEYWORDS |
GS_APP_KUDO_HI_DPI_ICON |
GS_APP_KUDO_SANDBOXED_SECURE |
GS_APP_KUDO_SANDBOXED);
g_assert_cmpstr (gs_app_get_origin_hostname (app), ==, "localhost");
g_assert_cmpstr (gs_app_get_version (app), ==, "1.2.3");
g_assert_cmpstr (gs_app_get_update_version (app), ==, NULL);
g_assert_cmpstr (gs_app_get_update_details_markup (app), ==, NULL);
g_assert_cmpint (gs_app_get_update_urgency (app), ==, AS_URGENCY_KIND_UNKNOWN);
/* check runtime */
runtime = gs_app_get_runtime (app);
g_assert_true (runtime != NULL);
g_assert_cmpstr (gs_app_get_unique_id (runtime), ==, "user/flatpak/test/org.test.Runtime/master");
g_assert_cmpint (gs_app_get_state (runtime), ==, GS_APP_STATE_AVAILABLE);
/* install, also installing runtime */
g_object_unref (plugin_job);
plugin_job = gs_plugin_job_install_apps_new (list,
GS_PLUGIN_INSTALL_APPS_FLAGS_NONE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_true (ret);
g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_INSTALLED);
g_assert_cmpstr (gs_app_get_version (app), ==, "1.2.3");
g_assert_true (gs_app_get_progress (app) == GS_APP_PROGRESS_UNKNOWN ||
gs_app_get_progress (app) == 100);
g_assert_cmpint (gs_app_get_state (runtime), ==, GS_APP_STATE_INSTALLED);
/* check the application exists in the right places */
metadata_fn = g_build_filename (root,
"flatpak",
"app",
"org.test.Chiron",
"current",
"active",
"metadata",
NULL);
g_assert_true (g_file_test (metadata_fn, G_FILE_TEST_IS_REGULAR));
desktop_fn = g_build_filename (root,
"flatpak",
"app",
"org.test.Chiron",
"current",
"active",
"export",
"share",
"applications",
"org.test.Chiron.desktop",
NULL);
g_assert_true (g_file_test (desktop_fn, G_FILE_TEST_IS_REGULAR));
/* check the runtime was installed as well */
runtime_fn = g_build_filename (root,
"flatpak",
"runtime",
"org.test.Runtime",
"x86_64",
"master",
"active",
"files",
"share",
"libtest",
"README",
NULL);
g_assert_true (g_file_test (runtime_fn, G_FILE_TEST_IS_REGULAR));
/* remove the application */
g_object_unref (plugin_job);
plugin_job = gs_plugin_job_uninstall_apps_new (list, GS_PLUGIN_UNINSTALL_APPS_FLAGS_NONE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
g_assert_no_error (error);
g_assert_true (ret);
g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_AVAILABLE);
g_assert_cmpint (gs_app_get_state (runtime), ==, GS_APP_STATE_INSTALLED);
g_assert_true (!g_file_test (metadata_fn, G_FILE_TEST_IS_REGULAR));
g_assert_true (!g_file_test (desktop_fn, G_FILE_TEST_IS_REGULAR));
/* install again, to check whether the progress gets initialized;
* since installation happens in another thread, we have to monitor all
* changes to the progress and see if we see the one we want */
seen_unknown = (gs_app_get_progress (app) == GS_APP_PROGRESS_UNKNOWN);
signal_id = g_signal_connect (app, "notify::progress",
G_CALLBACK (progress_notify_cb), &seen_unknown);
g_object_unref (plugin_job);
plugin_job = gs_plugin_job_install_apps_new (list,
GS_PLUGIN_INSTALL_APPS_FLAGS_NONE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
/* progress should be set to unknown right before installing */
while (!seen_unknown)
g_main_context_iteration (NULL, TRUE);
g_assert_true (seen_unknown);
g_assert_no_error (error);
g_assert_true (ret);
g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_INSTALLED);
g_assert_cmpstr (gs_app_get_version (app), ==, "1.2.3");
g_assert_true (gs_app_get_progress (app) == GS_APP_PROGRESS_UNKNOWN ||
gs_app_get_progress (app) == 100);
g_signal_handler_disconnect (app, signal_id);
/* remove the application */
g_object_unref (plugin_job);
plugin_job = gs_plugin_job_uninstall_apps_new (list, GS_PLUGIN_UNINSTALL_APPS_FLAGS_NONE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
g_assert_no_error (error);
g_assert_true (ret);
g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_AVAILABLE);
g_assert_cmpint (gs_app_get_state (runtime), ==, GS_APP_STATE_INSTALLED);
g_assert_true (!g_file_test (metadata_fn, G_FILE_TEST_IS_REGULAR));
g_assert_true (!g_file_test (desktop_fn, G_FILE_TEST_IS_REGULAR));
/* remove the remote (fail, as the runtime is still installed) */
g_object_unref (plugin_job);
plugin_job = gs_plugin_job_manage_repository_new (app_source, GS_PLUGIN_MANAGE_REPOSITORY_FLAGS_REMOVE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
g_assert_error (error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_FAILED);
g_assert_true (!ret);
g_clear_error (&error);
g_assert_cmpint (gs_app_get_state (app_source), ==, GS_APP_STATE_INSTALLED);
/* remove the runtime */
g_object_unref (plugin_job);
runtime_list = gs_app_list_new ();
gs_app_list_add (runtime_list, runtime);
plugin_job = gs_plugin_job_uninstall_apps_new (runtime_list, GS_PLUGIN_UNINSTALL_APPS_FLAGS_NONE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_true (ret);
g_assert_cmpint (gs_app_get_state (runtime), ==, GS_APP_STATE_AVAILABLE);
/* remove the remote */
g_object_unref (plugin_job);
plugin_job = gs_plugin_job_manage_repository_new (app_source, GS_PLUGIN_MANAGE_REPOSITORY_FLAGS_REMOVE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_true (ret);
g_assert_cmpint (gs_app_get_state (app_source), ==, GS_APP_STATE_UNAVAILABLE);
}
static void
gs_plugins_flatpak_app_missing_runtime_func (GsPluginLoader *plugin_loader)
{
GsApp *app;
gboolean ret;
g_autofree gchar *repodir_fn = NULL;
g_autofree gchar *testdir = NULL;
g_autofree gchar *testdir_repourl = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(GsApp) app_source = NULL;
g_autoptr(GsAppList) list = NULL;
g_autoptr(GsPluginJob) plugin_job = NULL;
GsPlugin *plugin;
g_autoptr(GsAppQuery) query = NULL;
const gchar *keywords[2] = { NULL, };
g_autoptr(GPtrArray) events_before = NULL;
g_autoptr(GPtrArray) events_after = NULL;
/* drop all caches */
gs_utils_rmtree (g_getenv ("GS_SELF_TEST_CACHEDIR"), NULL);
gs_test_reinitialise_plugin_loader (plugin_loader, allowlist, NULL);
/* no flatpak, abort */
if (!gs_plugin_loader_get_enabled (plugin_loader, "flatpak"))
return;
/* no files to use */
repodir_fn = gs_test_get_filename (TESTDATADIR, "app-missing-runtime/repo");
if (repodir_fn == NULL ||
!g_file_test (repodir_fn, G_FILE_TEST_EXISTS)) {
g_test_skip ("no flatpak test repo");
return;
}
/* add a remote */
app_source = gs_flatpak_app_new ("test");
testdir = gs_test_get_filename (TESTDATADIR, "app-missing-runtime");
if (testdir == NULL)
return;
testdir_repourl = g_strdup_printf ("file://%s/repo", testdir);
gs_app_set_kind (app_source, AS_COMPONENT_KIND_REPOSITORY);
plugin = gs_plugin_loader_find_plugin (plugin_loader, "flatpak");
gs_app_set_management_plugin (app_source, plugin);
gs_app_set_state (app_source, GS_APP_STATE_AVAILABLE);
gs_flatpak_app_set_repo_url (app_source, testdir_repourl);
plugin_job = gs_plugin_job_manage_repository_new (app_source, GS_PLUGIN_MANAGE_REPOSITORY_FLAGS_INSTALL);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_true (ret);
g_assert_cmpint (gs_app_get_state (app_source), ==, GS_APP_STATE_INSTALLED);
/* refresh the appstream metadata */
g_object_unref (plugin_job);
plugin_job = gs_plugin_job_refresh_metadata_new (G_MAXUINT64,
GS_PLUGIN_REFRESH_METADATA_FLAGS_NONE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
g_assert_no_error (error);
g_assert_true (ret);
/* find available application */
g_object_unref (plugin_job);
keywords[0] = "Bingo";
query = gs_app_query_new ("keywords", keywords,
"refine-flags", GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON,
"dedupe-flags", GS_PLUGIN_JOB_DEDUPE_FLAGS_DEFAULT,
"sort-func", gs_utils_app_sort_match_value,
NULL);
plugin_job = gs_plugin_job_list_apps_new (query, GS_PLUGIN_LIST_APPS_FLAGS_NONE);
g_clear_object (&query);
list = gs_plugin_loader_job_process (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_true (list != NULL);
/* make sure there is one entry, the flatpak app */
g_assert_cmpint (gs_app_list_length (list), ==, 1);
app = gs_app_list_index (list, 0);
g_assert_cmpstr (gs_app_get_id (app), ==, "org.test.Chiron");
g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_AVAILABLE);
/* Install, also installing runtime. This should fail because the
* runtime doesnt exist. Job failure should be reported as an event. */
g_object_unref (plugin_job);
events_before = gs_plugin_loader_get_events (plugin_loader);
plugin_job = gs_plugin_job_install_apps_new (list,
GS_PLUGIN_INSTALL_APPS_FLAGS_NONE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
g_assert_no_error (error);
g_assert_true (ret);
events_after = gs_plugin_loader_get_events (plugin_loader);
g_assert_cmpuint (events_after->len, >, events_before->len);
g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_AVAILABLE);
g_assert_cmpint (gs_app_get_progress (app), ==, GS_APP_PROGRESS_UNKNOWN);
/* remove the remote */
g_object_unref (plugin_job);
plugin_job = gs_plugin_job_manage_repository_new (app_source, GS_PLUGIN_MANAGE_REPOSITORY_FLAGS_REMOVE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_true (ret);
g_assert_cmpint (gs_app_get_state (app_source), ==, GS_APP_STATE_UNAVAILABLE);
}
static void
update_app_progress_notify_cb (GsApp *app, GParamSpec *pspec, gpointer user_data)
{
g_debug ("progress now %u%%", gs_app_get_progress (app));
if (user_data != NULL) {
guint *tmp = (guint *) user_data;
(*tmp)++;
}
}
static void
update_app_state_notify_cb (GsApp *app, GParamSpec *pspec, gpointer user_data)
{
GsAppState state = gs_app_get_state (app);
g_debug ("state now %s", gs_app_state_to_string (state));
if (state == GS_APP_STATE_INSTALLING) {
gboolean *tmp = (gboolean *) user_data;
*tmp = TRUE;
}
}
static gboolean
update_app_action_delay_cb (gpointer user_data)
{
GMainLoop *loop = (GMainLoop *) user_data;
g_main_loop_quit (loop);
return FALSE;
}
static void
update_app_action_finish_sync (GObject *source, GAsyncResult *res, gpointer user_data)
{
GsPluginLoader *plugin_loader = GS_PLUGIN_LOADER (source);
gboolean ret;
g_autoptr(GError) error = NULL;
ret = gs_plugin_loader_job_action_finish (plugin_loader, res, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_true (ret);
g_timeout_add_seconds (5, update_app_action_delay_cb, user_data);
}
static void
gs_plugins_flatpak_runtime_repo_func (GsPluginLoader *plugin_loader)
{
GsApp *app_source;
GsApp *runtime;
const gchar *fn_ref = "test.flatpakref";
const gchar *fn_repo = "test.flatpakrepo";
gboolean ret;
g_autoptr(GFile) fn_repo_file = NULL;
g_autofree gchar *fn_repourl = NULL;
g_autofree gchar *testdir2 = NULL;
g_autofree gchar *testdir2_repourl = NULL;
g_autofree gchar *testdir = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(GFile) file = NULL;
g_autoptr(GMainLoop) loop = g_main_loop_new (NULL, FALSE);
g_autoptr(GsApp) app = NULL;
g_autoptr(GsAppList) list = NULL;
g_autoptr(GsAppList) sources2 = NULL;
g_autoptr(GsAppList) sources = NULL;
g_autoptr(GsAppList) runtime_list = NULL;
g_autoptr(GsAppQuery) query = NULL;
g_autoptr(GsPluginJob) plugin_job = NULL;
/* drop all caches */
gs_utils_rmtree (g_getenv ("GS_SELF_TEST_CACHEDIR"), NULL);
gs_test_reinitialise_plugin_loader (plugin_loader, allowlist, NULL);
/* write a flatpakrepo file */
testdir = gs_test_get_filename (TESTDATADIR, "only-runtime");
if (testdir == NULL)
return;
ret = gs_flatpak_test_write_repo_file (fn_repo, testdir, &fn_repo_file, &error);
g_assert_no_error (error);
g_assert_true (ret);
/* write a flatpakref file */
fn_repourl = g_file_get_uri (fn_repo_file);
testdir2 = gs_test_get_filename (TESTDATADIR, "app-missing-runtime");
if (testdir2 == NULL)
return;
testdir2_repourl = g_strdup_printf ("file://%s/repo", testdir2);
ret = gs_flatpak_test_write_ref_file (fn_ref, testdir2_repourl, fn_repourl, &file, &error);
g_assert_no_error (error);
g_assert_true (ret);
/* convert it to a GsApp */
plugin_job = gs_plugin_job_file_to_app_new (file, GS_PLUGIN_FILE_TO_APP_FLAGS_NONE);
gs_plugin_job_set_refine_flags (plugin_job, GS_PLUGIN_REFINE_FLAGS_REQUIRE_VERSION |
GS_PLUGIN_REFINE_FLAGS_REQUIRE_RUNTIME);
app = gs_plugin_loader_job_process_app (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_true (app != NULL);
g_assert_cmpint (gs_app_get_kind (app), ==, AS_COMPONENT_KIND_DESKTOP_APP);
g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_AVAILABLE);
g_assert_cmpstr (gs_app_get_id (app), ==, "org.test.Chiron");
g_assert_true (as_utils_data_id_equal (gs_app_get_unique_id (app),
"user/flatpak/*/org.test.Chiron/master"));
g_assert_true (gs_app_get_local_file (app) != NULL);
/* get runtime */
runtime = gs_app_get_runtime (app);
g_assert_cmpstr (gs_app_get_unique_id (runtime), ==, "user/flatpak/test/org.test.Runtime/master");
g_assert_cmpint (gs_app_get_state (runtime), ==, GS_APP_STATE_AVAILABLE);
/* check the number of sources */
g_object_unref (plugin_job);
query = gs_app_query_new ("is-source", GS_APP_QUERY_TRISTATE_TRUE, NULL);
plugin_job = gs_plugin_job_list_apps_new (query, GS_PLUGIN_LIST_APPS_FLAGS_NONE);
g_clear_object (&query);
sources = gs_plugin_loader_job_process (plugin_loader, plugin_job,
NULL, &error);
g_assert_no_error (error);
g_assert_true (sources != NULL);
g_assert_cmpint (gs_app_list_length (sources), ==, 0);
/* install, which will install the runtime from the new remote */
g_object_unref (plugin_job);
list = gs_app_list_new ();
gs_app_list_add (list, app);
plugin_job = gs_plugin_job_install_apps_new (list,
GS_PLUGIN_INSTALL_APPS_FLAGS_NONE);
gs_plugin_loader_job_process_async (plugin_loader, plugin_job,
NULL,
update_app_action_finish_sync,
loop);
g_main_loop_run (loop);
gs_test_flush_main_context ();
g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_INSTALLED);
g_assert_cmpint (gs_app_get_state (runtime), ==, GS_APP_STATE_INSTALLED);
/* check the number of sources */
g_object_unref (plugin_job);
query = gs_app_query_new ("is-source", GS_APP_QUERY_TRISTATE_TRUE, NULL);
plugin_job = gs_plugin_job_list_apps_new (query, GS_PLUGIN_LIST_APPS_FLAGS_NONE);
g_clear_object (&query);
sources2 = gs_plugin_loader_job_process (plugin_loader, plugin_job, NULL, &error);
g_assert_no_error (error);
g_assert_true (sources2 != NULL);
g_assert_cmpint (gs_app_list_length (sources2), ==, 1);
/* remove the app */
g_object_unref (plugin_job);
plugin_job = gs_plugin_job_uninstall_apps_new (list, GS_PLUGIN_UNINSTALL_APPS_FLAGS_NONE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_true (ret);
g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_UNKNOWN);
/* remove the runtime */
g_object_unref (plugin_job);
runtime_list = gs_app_list_new ();
gs_app_list_add (runtime_list, runtime);
plugin_job = gs_plugin_job_uninstall_apps_new (runtime_list, GS_PLUGIN_UNINSTALL_APPS_FLAGS_NONE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_true (ret);
g_assert_cmpint (gs_app_get_state (runtime), ==, GS_APP_STATE_AVAILABLE);
/* remove the remote */
app_source = gs_app_list_index (sources2, 0);
g_assert_true (app_source != NULL);
g_assert_cmpstr (gs_app_get_unique_id (app_source), ==, "user/flatpak/*/test/*");
g_object_unref (plugin_job);
plugin_job = gs_plugin_job_manage_repository_new (app_source, GS_PLUGIN_MANAGE_REPOSITORY_FLAGS_REMOVE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_true (ret);
g_assert_cmpint (gs_app_get_state (app_source), ==, GS_APP_STATE_UNAVAILABLE);
}
/* same as gs_plugins_flatpak_runtime_repo_func, but this time manually
* installing the flatpakrepo BEFORE the flatpakref is installed */
static void
gs_plugins_flatpak_runtime_repo_redundant_func (GsPluginLoader *plugin_loader)
{
GsApp *app_source;
GsApp *runtime;
const gchar *fn_ref = "test.flatpakref";
const gchar *fn_repo = "test.flatpakrepo";
gboolean ret;
g_autofree gchar *fn_repourl = NULL;
g_autofree gchar *testdir2 = NULL;
g_autofree gchar *testdir2_repourl = NULL;
g_autofree gchar *testdir = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(GFile) file = NULL;
g_autoptr(GFile) file_repo = NULL;
g_autoptr(GsApp) app = NULL;
g_autoptr(GsApp) app_src = NULL;
g_autoptr(GsAppList) list = NULL;
g_autoptr(GsAppList) sources2 = NULL;
g_autoptr(GsAppList) sources = NULL;
g_autoptr(GsAppList) runtime_list = NULL;
g_autoptr(GsAppQuery) query = NULL;
g_autoptr(GsPluginJob) plugin_job = NULL;
/* drop all caches */
gs_utils_rmtree (g_getenv ("GS_SELF_TEST_CACHEDIR"), NULL);
gs_test_reinitialise_plugin_loader (plugin_loader, allowlist, NULL);
/* write a flatpakrepo file */
testdir = gs_test_get_filename (TESTDATADIR, "only-runtime");
if (testdir == NULL)
return;
ret = gs_flatpak_test_write_repo_file (fn_repo, testdir, &file_repo, &error);
g_assert_no_error (error);
g_assert_true (ret);
/* convert it to a GsApp */
plugin_job = gs_plugin_job_file_to_app_new (file_repo, GS_PLUGIN_FILE_TO_APP_FLAGS_NONE);
gs_plugin_job_set_refine_flags (plugin_job, GS_PLUGIN_REFINE_FLAGS_REQUIRE_VERSION |
GS_PLUGIN_REFINE_FLAGS_REQUIRE_RUNTIME);
app_src = gs_plugin_loader_job_process_app (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_true (app_src != NULL);
g_assert_cmpint (gs_app_get_kind (app_src), ==, AS_COMPONENT_KIND_REPOSITORY);
g_assert_cmpint (gs_app_get_state (app_src), ==, GS_APP_STATE_AVAILABLE_LOCAL);
g_assert_cmpstr (gs_app_get_id (app_src), ==, "test");
g_assert_cmpstr (gs_app_get_unique_id (app_src), ==, "user/*/*/test/master");
g_assert_true (gs_app_get_local_file (app_src) != NULL);
/* install the source manually */
g_object_unref (plugin_job);
plugin_job = gs_plugin_job_manage_repository_new (app_src, GS_PLUGIN_MANAGE_REPOSITORY_FLAGS_INSTALL);;
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_true (ret);
g_assert_cmpint (gs_app_get_state (app_src), ==, GS_APP_STATE_INSTALLED);
/* write a flatpakref file */
fn_repourl = g_file_get_uri (file_repo);
testdir2 = gs_test_get_filename (TESTDATADIR, "app-missing-runtime");
if (testdir2 == NULL)
return;
testdir2_repourl = g_strdup_printf ("file://%s/repo", testdir2);
ret = gs_flatpak_test_write_ref_file (fn_ref, testdir2_repourl, fn_repourl, &file, &error);
g_assert_no_error (error);
g_assert_true (ret);
/* convert it to a GsApp */
g_object_unref (plugin_job);
plugin_job = gs_plugin_job_file_to_app_new (file, GS_PLUGIN_FILE_TO_APP_FLAGS_NONE);
gs_plugin_job_set_refine_flags (plugin_job, GS_PLUGIN_REFINE_FLAGS_REQUIRE_VERSION |
GS_PLUGIN_REFINE_FLAGS_REQUIRE_RUNTIME);
app = gs_plugin_loader_job_process_app (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_true (app != NULL);
g_assert_cmpint (gs_app_get_kind (app), ==, AS_COMPONENT_KIND_DESKTOP_APP);
g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_AVAILABLE);
g_assert_cmpstr (gs_app_get_id (app), ==, "org.test.Chiron");
g_assert_true (as_utils_data_id_equal (gs_app_get_unique_id (app),
"user/flatpak/*/org.test.Chiron/master"));
g_assert_true (gs_app_get_local_file (app) != NULL);
/* get runtime */
runtime = gs_app_get_runtime (app);
g_assert_cmpstr (gs_app_get_unique_id (runtime), ==, "user/flatpak/test/org.test.Runtime/master");
g_assert_cmpint (gs_app_get_state (runtime), ==, GS_APP_STATE_AVAILABLE);
/* check the number of sources */
g_object_unref (plugin_job);
query = gs_app_query_new ("is-source", GS_APP_QUERY_TRISTATE_TRUE, NULL);
plugin_job = gs_plugin_job_list_apps_new (query, GS_PLUGIN_LIST_APPS_FLAGS_NONE);
g_clear_object (&query);
sources = gs_plugin_loader_job_process (plugin_loader, plugin_job,
NULL, &error);
g_assert_no_error (error);
g_assert_true (sources != NULL);
g_assert_cmpint (gs_app_list_length (sources), ==, 1); /* repo */
/* install, which will NOT install the runtime from the RuntimeRemote,
* but from the existing test repo */
g_object_unref (plugin_job);
list = gs_app_list_new ();
gs_app_list_add (list, app);
plugin_job = gs_plugin_job_install_apps_new (list,
GS_PLUGIN_INSTALL_APPS_FLAGS_NONE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_true (ret);
g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_INSTALLED);
g_assert_cmpint (gs_app_get_state (runtime), ==, GS_APP_STATE_INSTALLED);
/* check the number of sources */
g_object_unref (plugin_job);
query = gs_app_query_new ("is-source", GS_APP_QUERY_TRISTATE_TRUE, NULL);
plugin_job = gs_plugin_job_list_apps_new (query, GS_PLUGIN_LIST_APPS_FLAGS_NONE);
g_clear_object (&query);
sources2 = gs_plugin_loader_job_process (plugin_loader, plugin_job, NULL, &error);
g_assert_no_error (error);
g_assert_true (sources2 != NULL);
/* remove the app */
g_object_unref (plugin_job);
plugin_job = gs_plugin_job_uninstall_apps_new (list, GS_PLUGIN_UNINSTALL_APPS_FLAGS_NONE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_true (ret);
g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_UNKNOWN);
/* remove the runtime */
g_object_unref (plugin_job);
runtime_list = gs_app_list_new ();
gs_app_list_add (runtime_list, runtime);
plugin_job = gs_plugin_job_uninstall_apps_new (runtime_list, GS_PLUGIN_UNINSTALL_APPS_FLAGS_NONE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_true (ret);
g_assert_cmpint (gs_app_get_state (runtime), ==, GS_APP_STATE_AVAILABLE);
/* remove the remote */
app_source = gs_app_list_index (sources2, 0);
g_assert_true (app_source != NULL);
g_assert_cmpstr (gs_app_get_unique_id (app_source), ==, "user/flatpak/*/test/*");
g_object_unref (plugin_job);
plugin_job = gs_plugin_job_manage_repository_new (app_source, GS_PLUGIN_MANAGE_REPOSITORY_FLAGS_REMOVE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_true (ret);
g_assert_cmpint (gs_app_get_state (app_source), ==, GS_APP_STATE_UNAVAILABLE);
}
static void
gs_plugins_flatpak_broken_remote_func (GsPluginLoader *plugin_loader)
{
gboolean ret;
const gchar *fn = "test.flatpakref";
const gchar *fn_repo = "test.flatpakrepo";
g_autoptr(GFile) fn_repo_file = NULL;
g_autofree gchar *fn_repourl = NULL;
g_autofree gchar *testdir2 = NULL;
g_autofree gchar *testdir2_repourl = NULL;
g_autofree gchar *testdir = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(GFile) file = NULL;
g_autoptr(GsApp) app = NULL;
g_autoptr(GsApp) app_source = NULL;
g_autoptr(GsPluginJob) plugin_job = NULL;
GsPlugin *plugin;
/* drop all caches */
gs_utils_rmtree (g_getenv ("GS_SELF_TEST_CACHEDIR"), NULL);
gs_test_reinitialise_plugin_loader (plugin_loader, allowlist, NULL);
/* no flatpak, abort */
if (!gs_plugin_loader_get_enabled (plugin_loader, "flatpak"))
return;
/* add a remote with only the runtime in */
app_source = gs_flatpak_app_new ("test");
testdir = gs_test_get_filename (TESTDATADIR, "only-runtime");
if (testdir == NULL)
return;
gs_app_set_kind (app_source, AS_COMPONENT_KIND_REPOSITORY);
plugin = gs_plugin_loader_find_plugin (plugin_loader, "flatpak");
gs_app_set_management_plugin (app_source, plugin);
gs_app_set_state (app_source, GS_APP_STATE_AVAILABLE);
gs_flatpak_app_set_repo_url (app_source, "file:///wont/work");
plugin_job = gs_plugin_job_manage_repository_new (app_source, GS_PLUGIN_MANAGE_REPOSITORY_FLAGS_INSTALL);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
g_assert_no_error (error);
g_assert_true (ret);
g_assert_cmpint (gs_app_get_state (app_source), ==, GS_APP_STATE_INSTALLED);
/* write a flatpakrepo file (the flatpakref below must have a RuntimeRepo=
* to avoid a warning) */
testdir2 = gs_test_get_filename (TESTDATADIR, "app-with-runtime");
if (testdir2 == NULL)
return;
ret = gs_flatpak_test_write_repo_file (fn_repo, testdir2, &fn_repo_file, &error);
g_assert_no_error (error);
g_assert_true (ret);
/* write a flatpakref file */
fn_repourl = g_file_get_uri (fn_repo_file);
testdir2_repourl = g_strdup_printf ("file://%s/repo", testdir2);
ret = gs_flatpak_test_write_ref_file (fn, testdir2_repourl, fn_repourl, &file, &error);
g_assert_no_error (error);
g_assert_true (ret);
/* convert it to a GsApp */
g_object_unref (plugin_job);
plugin_job = gs_plugin_job_file_to_app_new (file, GS_PLUGIN_FILE_TO_APP_FLAGS_NONE);
gs_plugin_job_set_refine_flags (plugin_job, GS_PLUGIN_REFINE_FLAGS_REQUIRE_VERSION);
app = gs_plugin_loader_job_process_app (plugin_loader, plugin_job, NULL, &error);
g_assert_no_error (error);
g_assert_true (app != NULL);
g_assert_cmpint (gs_app_get_kind (app), ==, AS_COMPONENT_KIND_DESKTOP_APP);
g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_AVAILABLE);
g_assert_cmpstr (gs_app_get_id (app), ==, "org.test.Chiron");
g_assert_true (as_utils_data_id_equal (gs_app_get_unique_id (app),
"user/flatpak/test/org.test.Chiron/master"));
g_assert_cmpstr (gs_app_get_url (app, AS_URL_KIND_HOMEPAGE), ==, "http://127.0.0.1/");
g_assert_cmpstr (gs_app_get_name (app), ==, "Chiron");
g_assert_cmpstr (gs_app_get_summary (app), ==, "Single line synopsis");
g_assert_cmpstr (gs_app_get_description (app), ==, "Long description.");
g_assert_cmpstr (gs_app_get_version (app), ==, "1.2.3");
g_assert_true (gs_app_get_local_file (app) != NULL);
/* remove source */
g_object_unref (plugin_job);
plugin_job = gs_plugin_job_manage_repository_new (app_source, GS_PLUGIN_MANAGE_REPOSITORY_FLAGS_REMOVE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
g_assert_no_error (error);
g_assert_true (ret);
}
static void
flatpak_bundle_or_ref_helper (GsPluginLoader *plugin_loader,
gboolean is_bundle)
{
GsApp *app_tmp;
GsApp *runtime;
gboolean ret;
GsPluginRefineFlags refine_flags;
g_autofree gchar *fn = NULL;
g_autofree gchar *testdir = NULL;
g_autofree gchar *testdir_repourl = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(GFile) file = NULL;
g_autoptr(GsApp) app = NULL;
g_autoptr(GsApp) app2 = NULL;
g_autoptr(GsApp) app_source = NULL;
g_autoptr(GsAppList) list = NULL;
g_autoptr(GsAppList) search1 = NULL;
g_autoptr(GsAppList) search2 = NULL;
g_autoptr(GsAppList) sources = NULL;
g_autoptr(GsAppList) app_list = NULL;
g_autoptr(GsAppList) app2_list = NULL;
g_autoptr(GsAppList) runtime_list = NULL;
g_autoptr(GsPluginJob) plugin_job = NULL;
GsPlugin *plugin;
g_autoptr(GsAppQuery) query = NULL;
const gchar *keywords[2] = { NULL, };
/* drop all caches */
gs_utils_rmtree (g_getenv ("GS_SELF_TEST_CACHEDIR"), NULL);
gs_test_reinitialise_plugin_loader (plugin_loader, allowlist, NULL);
/* no flatpak, abort */
if (!gs_plugin_loader_get_enabled (plugin_loader, "flatpak"))
return;
/* add a remote with only the runtime in */
app_source = gs_flatpak_app_new ("test");
testdir = gs_test_get_filename (TESTDATADIR, "only-runtime");
if (testdir == NULL)
return;
testdir_repourl = g_strdup_printf ("file://%s/repo", testdir);
gs_app_set_kind (app_source, AS_COMPONENT_KIND_REPOSITORY);
plugin = gs_plugin_loader_find_plugin (plugin_loader, "flatpak");
gs_app_set_management_plugin (app_source, plugin);
gs_app_set_state (app_source, GS_APP_STATE_AVAILABLE);
gs_flatpak_app_set_repo_url (app_source, testdir_repourl);
plugin_job = gs_plugin_job_manage_repository_new (app_source, GS_PLUGIN_MANAGE_REPOSITORY_FLAGS_INSTALL);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
g_assert_no_error (error);
g_assert_true (ret);
g_assert_cmpint (gs_app_get_state (app_source), ==, GS_APP_STATE_INSTALLED);
/* refresh the appstream metadata */
g_object_unref (plugin_job);
plugin_job = gs_plugin_job_refresh_metadata_new (0,
GS_PLUGIN_REFRESH_METADATA_FLAGS_NONE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
g_assert_no_error (error);
g_assert_true (ret);
/* find available application */
g_object_unref (plugin_job);
keywords[0] = "runtime";
query = gs_app_query_new ("keywords", keywords,
"refine-flags", GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON,
"dedupe-flags", GS_PLUGIN_JOB_DEDUPE_FLAGS_DEFAULT,
"sort-func", gs_utils_app_sort_match_value,
NULL);
plugin_job = gs_plugin_job_list_apps_new (query, GS_PLUGIN_LIST_APPS_FLAGS_NONE);
g_clear_object (&query);
list = gs_plugin_loader_job_process (plugin_loader, plugin_job, NULL, &error);
g_assert_no_error (error);
g_assert_true (list != NULL);
/* make sure there is one entry, the flatpak runtime */
g_assert_cmpint (gs_app_list_length (list), ==, 1);
runtime = gs_app_list_index (list, 0);
g_assert_cmpstr (gs_app_get_id (runtime), ==, "org.test.Runtime");
g_assert_cmpstr (gs_app_get_unique_id (runtime), ==, "user/flatpak/test/org.test.Runtime/master");
g_assert_cmpint (gs_app_get_state (runtime), ==, GS_APP_STATE_AVAILABLE);
/* install the runtime ahead of time */
g_object_unref (plugin_job);
plugin_job = gs_plugin_job_install_apps_new (list,
GS_PLUGIN_INSTALL_APPS_FLAGS_NONE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
g_assert_no_error (error);
g_assert_true (ret);
g_assert_cmpint (gs_app_get_state (runtime), ==, GS_APP_STATE_INSTALLED);
if (is_bundle) {
/* find the flatpak bundle file */
fn = gs_test_get_filename (TESTDATADIR, "chiron.flatpak");
g_assert_true (fn != NULL);
file = g_file_new_for_path (fn);
refine_flags = GS_PLUGIN_REFINE_FLAGS_NONE;
} else {
const gchar *fn_repo = "test.flatpakrepo";
g_autoptr(GFile) fn_repo_file = NULL;
g_autofree gchar *fn_repourl = NULL;
g_autofree gchar *testdir2 = NULL;
g_autofree gchar *testdir2_repourl = NULL;
/* write a flatpakrepo file (the flatpakref below must have a RuntimeRepo=
* to avoid a warning) */
testdir2 = gs_test_get_filename (TESTDATADIR, "app-with-runtime");
if (testdir2 == NULL)
return;
ret = gs_flatpak_test_write_repo_file (fn_repo, testdir2, &fn_repo_file, &error);
g_assert_no_error (error);
g_assert_true (ret);
/* write a flatpakref file */
fn_repourl = g_file_get_uri (fn_repo_file);
testdir2_repourl = g_strdup_printf ("file://%s/repo", testdir2);
fn = g_strdup ("test.flatpakref");
ret = gs_flatpak_test_write_ref_file (fn, testdir2_repourl, fn_repourl, &file, &error);
g_assert_no_error (error);
g_assert_true (ret);
refine_flags = GS_PLUGIN_REFINE_FLAGS_REQUIRE_VERSION |
GS_PLUGIN_REFINE_FLAGS_REQUIRE_URL |
GS_PLUGIN_REFINE_FLAGS_REQUIRE_DESCRIPTION |
GS_PLUGIN_REFINE_FLAGS_REQUIRE_RUNTIME;
}
/* Wait for the flatpak changes to be delivered through the file
monitor notifications, which will cleanup plugin cache. */
g_usleep (G_USEC_PER_SEC);
/* convert it to a GsApp */
g_object_unref (plugin_job);
plugin_job = gs_plugin_job_file_to_app_new (file, GS_PLUGIN_FILE_TO_APP_FLAGS_NONE);
gs_plugin_job_set_refine_flags (plugin_job, refine_flags);
app = gs_plugin_loader_job_process_app (plugin_loader, plugin_job, NULL, &error);
g_assert_no_error (error);
g_assert_true (app != NULL);
g_assert_cmpint (gs_app_get_kind (app), ==, AS_COMPONENT_KIND_DESKTOP_APP);
g_assert_cmpstr (gs_app_get_id (app), ==, "org.test.Chiron");
g_assert_cmpstr (gs_app_get_name (app), ==, "Chiron");
g_assert_cmpstr (gs_app_get_summary (app), ==, "Single line synopsis");
g_assert_cmpstr (gs_app_get_version (app), ==, "1.2.3");
g_assert_true (gs_app_get_local_file (app) != NULL);
if (is_bundle) {
/* Note: The origin is set to "flatpak" here because an origin remote
* won't be created until the app is installed.
*/
g_assert_true (as_utils_data_id_equal (gs_app_get_unique_id (app),
"user/flatpak/flatpak/org.test.Chiron/master"));
g_assert_true (gs_flatpak_app_get_file_kind (app) == GS_FLATPAK_APP_FILE_KIND_BUNDLE);
g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_AVAILABLE_LOCAL);
} else {
g_assert_true (as_utils_data_id_equal (gs_app_get_unique_id (app),
"user/flatpak/test/org.test.Chiron/master"));
g_assert_true (gs_flatpak_app_get_file_kind (app) == GS_FLATPAK_APP_FILE_KIND_REF);
g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_AVAILABLE);
g_assert_cmpstr (gs_app_get_url (app, AS_URL_KIND_HOMEPAGE), ==, "http://127.0.0.1/");
g_assert_cmpstr (gs_app_get_description (app), ==, "Long description.");
}
/* get runtime */
runtime = gs_app_get_runtime (app);
g_assert_cmpstr (gs_app_get_unique_id (runtime), ==, "user/flatpak/test/org.test.Runtime/master");
g_assert_cmpint (gs_app_get_state (runtime), ==, GS_APP_STATE_INSTALLED);
/* install */
g_object_unref (plugin_job);
app_list = gs_app_list_new ();
gs_app_list_add (app_list, app);
plugin_job = gs_plugin_job_install_apps_new (app_list,
GS_PLUGIN_INSTALL_APPS_FLAGS_NONE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
g_assert_no_error (error);
g_assert_true (ret);
g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_INSTALLED);
g_assert_cmpstr (gs_app_get_version (app), ==, "1.2.3");
g_assert_cmpstr (gs_app_get_update_version (app), ==, NULL);
g_assert_cmpstr (gs_app_get_update_details_markup (app), ==, NULL);
/* search for the application */
g_object_unref (plugin_job);
keywords[0] = "chiron";
query = gs_app_query_new ("keywords", keywords,
"refine-flags", GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON,
"dedupe-flags", GS_PLUGIN_JOB_DEDUPE_FLAGS_DEFAULT,
"sort-func", gs_utils_app_sort_match_value,
NULL);
plugin_job = gs_plugin_job_list_apps_new (query, GS_PLUGIN_LIST_APPS_FLAGS_NONE);
g_clear_object (&query);
search1 = gs_plugin_loader_job_process (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_true (search1 != NULL);
g_assert_cmpint (gs_app_list_length (search1), ==, 1);
app_tmp = gs_app_list_index (search1, 0);
g_assert_cmpstr (gs_app_get_id (app_tmp), ==, "org.test.Chiron");
/* convert it to a GsApp again, and get the installed thing */
g_object_unref (plugin_job);
plugin_job = gs_plugin_job_file_to_app_new (file, GS_PLUGIN_FILE_TO_APP_FLAGS_NONE);
gs_plugin_job_set_refine_flags (plugin_job, GS_PLUGIN_REFINE_FLAGS_REQUIRE_VERSION |
GS_PLUGIN_REFINE_FLAGS_REQUIRE_RUNTIME);
app2 = gs_plugin_loader_job_process_app (plugin_loader, plugin_job, NULL, &error);
g_assert_no_error (error);
g_assert_true (app2 != NULL);
g_assert_cmpint (gs_app_get_state (app2), ==, GS_APP_STATE_INSTALLED);
if (is_bundle) {
g_assert_true (as_utils_data_id_equal (gs_app_get_unique_id (app2),
"user/flatpak/chiron-origin/org.test.Chiron/master"));
} else {
/* Note: the origin is now test-1 because that remote was created from the
* RuntimeRepo= setting
*/
g_assert_true (as_utils_data_id_equal (gs_app_get_unique_id (app2),
"user/flatpak/test-1/org.test.Chiron/master"));
}
/* remove app */
g_object_unref (plugin_job);
app2_list = gs_app_list_new ();
gs_app_list_add (app2_list, app2);
plugin_job = gs_plugin_job_uninstall_apps_new (app2_list, GS_PLUGIN_UNINSTALL_APPS_FLAGS_NONE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
g_assert_no_error (error);
g_assert_true (ret);
/* remove runtime */
g_object_unref (plugin_job);
runtime_list = gs_app_list_new ();
gs_app_list_add (runtime_list, runtime);
plugin_job = gs_plugin_job_uninstall_apps_new (runtime_list, GS_PLUGIN_UNINSTALL_APPS_FLAGS_NONE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
g_assert_no_error (error);
g_assert_true (ret);
/* remove source */
g_object_unref (plugin_job);
plugin_job = gs_plugin_job_manage_repository_new (app_source, GS_PLUGIN_MANAGE_REPOSITORY_FLAGS_REMOVE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
g_assert_no_error (error);
g_assert_true (ret);
if (!is_bundle) {
/* remove remote added by RuntimeRepo= in flatpakref */
g_autoptr(GsApp) runtime_source = gs_flatpak_app_new ("test-1");
gs_app_set_kind (runtime_source, AS_COMPONENT_KIND_REPOSITORY);
plugin = gs_plugin_loader_find_plugin (plugin_loader, "flatpak");
gs_app_set_management_plugin (runtime_source, plugin);
gs_app_set_state (runtime_source, GS_APP_STATE_INSTALLED);
g_object_unref (plugin_job);
plugin_job = gs_plugin_job_manage_repository_new (runtime_source, GS_PLUGIN_MANAGE_REPOSITORY_FLAGS_REMOVE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
g_assert_no_error (error);
g_assert_true (ret);
}
/* there should be no sources now */
g_object_unref (plugin_job);
query = gs_app_query_new ("is-source", GS_APP_QUERY_TRISTATE_TRUE, NULL);
plugin_job = gs_plugin_job_list_apps_new (query, GS_PLUGIN_LIST_APPS_FLAGS_NONE);
g_clear_object (&query);
sources = gs_plugin_loader_job_process (plugin_loader, plugin_job, NULL, &error);
g_assert_no_error (error);
g_assert_true (sources != NULL);
g_assert_cmpint (gs_app_list_length (sources), ==, 0);
/* there should be no matches now */
g_object_unref (plugin_job);
keywords[0] = "chiron";
query = gs_app_query_new ("keywords", keywords,
"refine-flags", GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON,
"dedupe-flags", GS_PLUGIN_JOB_DEDUPE_FLAGS_DEFAULT,
"sort-func", gs_utils_app_sort_match_value,
NULL);
plugin_job = gs_plugin_job_list_apps_new (query, GS_PLUGIN_LIST_APPS_FLAGS_NONE);
g_clear_object (&query);
search2 = gs_plugin_loader_job_process (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_true (search2 != NULL);
g_assert_cmpint (gs_app_list_length (search2), ==, 0);
}
static void
gs_plugins_flatpak_ref_func (GsPluginLoader *plugin_loader)
{
flatpak_bundle_or_ref_helper (plugin_loader, FALSE);
}
static void
gs_plugins_flatpak_bundle_func (GsPluginLoader *plugin_loader)
{
flatpak_bundle_or_ref_helper (plugin_loader, TRUE);
}
static void
gs_plugins_flatpak_count_signal_cb (GsPluginLoader *plugin_loader, guint *cnt)
{
if (cnt != NULL)
(*cnt)++;
}
static void
gs_plugins_flatpak_app_update_func (GsPluginLoader *plugin_loader)
{
GsApp *app;
GsApp *app_tmp;
GsApp *runtime;
gboolean got_progress_installing = FALSE;
gboolean ret;
guint notify_progress_id;
guint notify_state_id;
guint pending_app_changed_cnt = 0;
guint pending_apps_changed_id;
guint progress_cnt = 0;
guint updates_changed_cnt = 0;
guint updates_changed_id;
g_autofree gchar *repodir1_fn = NULL;
g_autofree gchar *repodir2_fn = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(GsApp) app_source = NULL;
g_autoptr(GsApp) old_runtime = NULL;
g_autoptr(GsAppList) list = NULL;
g_autoptr(GsAppList) list_updates = NULL;
g_autoptr(GsAppList) old_runtime_list = NULL;
g_autoptr(GsAppList) runtime_list = NULL;
g_autoptr(GsPluginJob) plugin_job = NULL;
g_autoptr(GMainLoop) loop = g_main_loop_new (NULL, FALSE);
g_autofree gchar *repo_path = NULL;
g_autofree gchar *repo_url = NULL;
GsPlugin *plugin;
g_autoptr(GsAppQuery) query = NULL;
const gchar *keywords[2] = { NULL, };
g_autoptr(GsAppList) update_apps_list = NULL;
/* drop all caches */
gs_utils_rmtree (g_getenv ("GS_SELF_TEST_CACHEDIR"), NULL);
gs_test_reinitialise_plugin_loader (plugin_loader, allowlist, NULL);
/* no flatpak, abort */
if (!gs_plugin_loader_get_enabled (plugin_loader, "flatpak"))
return;
/* no files to use */
repodir1_fn = gs_test_get_filename (TESTDATADIR, "app-with-runtime/repo");
if (repodir1_fn == NULL ||
!g_file_test (repodir1_fn, G_FILE_TEST_EXISTS)) {
g_test_skip ("no flatpak test repo");
return;
}
repodir2_fn = gs_test_get_filename (TESTDATADIR, "app-update/repo");
if (repodir2_fn == NULL ||
!g_file_test (repodir2_fn, G_FILE_TEST_EXISTS)) {
g_test_skip ("no flatpak test repo");
return;
}
/* add indirection so we can switch this after install */
repo_path = g_build_filename (g_getenv ("GS_SELF_TEST_FLATPAK_DATADIR"), "repo", NULL);
unlink (repo_path);
g_assert_true (symlink (repodir1_fn, repo_path) == 0);
/* add a remote */
app_source = gs_flatpak_app_new ("test");
gs_app_set_kind (app_source, AS_COMPONENT_KIND_REPOSITORY);
plugin = gs_plugin_loader_find_plugin (plugin_loader, "flatpak");
gs_app_set_management_plugin (app_source, plugin);
gs_app_set_state (app_source, GS_APP_STATE_AVAILABLE);
repo_url = g_strdup_printf ("file://%s", repo_path);
gs_flatpak_app_set_repo_url (app_source, repo_url);
plugin_job = gs_plugin_job_manage_repository_new (app_source, GS_PLUGIN_MANAGE_REPOSITORY_FLAGS_INSTALL);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_true (ret);
g_assert_cmpint (gs_app_get_state (app_source), ==, GS_APP_STATE_INSTALLED);
/* refresh the appstream metadata */
g_object_unref (plugin_job);
plugin_job = gs_plugin_job_refresh_metadata_new (G_MAXUINT64,
GS_PLUGIN_REFRESH_METADATA_FLAGS_NONE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_true (ret);
/* find available application */
g_object_unref (plugin_job);
keywords[0] = "Bingo";
query = gs_app_query_new ("keywords", keywords,
"refine-flags", GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON |
GS_PLUGIN_REFINE_FLAGS_REQUIRE_RUNTIME,
"dedupe-flags", GS_PLUGIN_JOB_DEDUPE_FLAGS_DEFAULT,
"sort-func", gs_utils_app_sort_match_value,
NULL);
plugin_job = gs_plugin_job_list_apps_new (query, GS_PLUGIN_LIST_APPS_FLAGS_NONE);
g_clear_object (&query);
list = gs_plugin_loader_job_process (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_true (list != NULL);
/* make sure there is one entry, the flatpak app */
g_assert_cmpint (gs_app_list_length (list), ==, 1);
app = gs_app_list_index (list, 0);
g_assert_cmpstr (gs_app_get_id (app), ==, "org.test.Chiron");
g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_AVAILABLE);
/* install, also installing runtime */
g_object_unref (plugin_job);
plugin_job = gs_plugin_job_install_apps_new (list,
GS_PLUGIN_INSTALL_APPS_FLAGS_NONE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_true (ret);
g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_INSTALLED);
g_assert_cmpstr (gs_app_get_version (app), ==, "1.2.3");
g_assert_cmpstr (gs_app_get_update_version (app), ==, NULL);
g_assert_cmpstr (gs_app_get_update_details_markup (app), ==, NULL);
/* switch to the new repo */
g_assert_true (unlink (repo_path) == 0);
g_assert_true (symlink (repodir2_fn, repo_path) == 0);
/* refresh the appstream metadata */
g_object_unref (plugin_job);
plugin_job = gs_plugin_job_refresh_metadata_new (0, /* force now */
GS_PLUGIN_REFRESH_METADATA_FLAGS_NONE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
g_assert_no_error (error);
g_assert_true (ret);
/* get the updates list */
g_object_unref (plugin_job);
query = gs_app_query_new ("is-for-update", GS_APP_QUERY_TRISTATE_TRUE,
"refine-flags", GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON |
GS_PLUGIN_REFINE_FLAGS_REQUIRE_UPDATE_DETAILS,
NULL);
plugin_job = gs_plugin_job_list_apps_new (query, GS_PLUGIN_LIST_APPS_FLAGS_NONE);
g_clear_object (&query);
list_updates = gs_plugin_loader_job_process (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_true (list_updates != NULL);
/* make sure there is one entry */
g_assert_cmpint (gs_app_list_length (list_updates), ==, 1);
for (guint i = 0; i < gs_app_list_length (list_updates); i++) {
app_tmp = gs_app_list_index (list_updates, i);
g_debug ("got update %s", gs_app_get_unique_id (app_tmp));
}
/* check that the runtime is not the update's one */
old_runtime = gs_app_get_runtime (app);
g_assert_true (old_runtime != NULL);
g_object_ref (old_runtime);
g_assert_cmpstr (gs_app_get_branch (old_runtime), !=, "new_master");
/* use the returned app, which can be a different object instance from previously */
app = gs_app_list_lookup (list_updates, "*/flatpak/test/org.test.Chiron/*");
g_assert_nonnull (app);
g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_UPDATABLE_LIVE);
g_assert_cmpstr (gs_app_get_update_details_markup (app), ==, "Version 1.2.4:\nThis is best.");
g_assert_cmpstr (gs_app_get_update_version (app), ==, "1.2.4");
/* care about signals */
pending_apps_changed_id =
g_signal_connect (plugin_loader, "pending-apps-changed",
G_CALLBACK (gs_plugins_flatpak_count_signal_cb),
&pending_app_changed_cnt);
updates_changed_id =
g_signal_connect (plugin_loader, "updates-changed",
G_CALLBACK (gs_plugins_flatpak_count_signal_cb),
&updates_changed_cnt);
notify_state_id =
g_signal_connect (app, "notify::state",
G_CALLBACK (update_app_state_notify_cb),
&got_progress_installing);
notify_progress_id =
g_signal_connect (app, "notify::progress",
G_CALLBACK (update_app_progress_notify_cb),
&progress_cnt);
/* use a mainloop so we get the events in the default context */
g_object_unref (plugin_job);
update_apps_list = gs_app_list_new ();
gs_app_list_add (update_apps_list, app);
plugin_job = gs_plugin_job_update_apps_new (update_apps_list, GS_PLUGIN_UPDATE_APPS_FLAGS_NO_DOWNLOAD);
gs_plugin_loader_job_process_async (plugin_loader, plugin_job,
NULL,
update_app_action_finish_sync,
loop);
g_main_loop_run (loop);
gs_test_flush_main_context ();
g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_INSTALLED);
g_assert_cmpstr (gs_app_get_version (app), ==, "1.2.4");
g_assert_cmpstr (gs_app_get_update_version (app), ==, NULL);
g_assert_cmpstr (gs_app_get_update_details_markup (app), ==, NULL);
g_assert_true (gs_app_get_progress (app) == GS_APP_PROGRESS_UNKNOWN ||
gs_app_get_progress (app) == 100);
g_assert_true (got_progress_installing);
//g_assert_cmpint (progress_cnt, >, 20); //FIXME: bug in OSTree
g_assert_cmpint (pending_app_changed_cnt, ==, 0);
g_assert_cmpint (updates_changed_cnt, ==, 1);
/* check that the app's runtime has changed */
runtime = gs_app_get_runtime (app);
g_assert_true (runtime != NULL);
g_assert_cmpstr (gs_app_get_unique_id (runtime), ==, "user/flatpak/test/org.test.Runtime/new_master");
g_assert_true (old_runtime != runtime);
g_assert_cmpstr (gs_app_get_branch (runtime), ==, "new_master");
g_assert_true (gs_app_get_state (runtime) == GS_APP_STATE_INSTALLED);
/* no longer care */
g_signal_handler_disconnect (plugin_loader, pending_apps_changed_id);
g_signal_handler_disconnect (plugin_loader, updates_changed_id);
g_signal_handler_disconnect (app, notify_state_id);
g_signal_handler_disconnect (app, notify_progress_id);
/* remove the app */
g_object_unref (plugin_job);
plugin_job = gs_plugin_job_uninstall_apps_new (update_apps_list, GS_PLUGIN_UNINSTALL_APPS_FLAGS_NONE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
g_assert_no_error (error);
g_assert_true (ret);
/* remove the old_runtime */
g_assert_cmpstr (gs_app_get_unique_id (old_runtime), ==, "user/flatpak/test/org.test.Runtime/master");
g_object_unref (plugin_job);
old_runtime_list = gs_app_list_new ();
gs_app_list_add (old_runtime_list, old_runtime);
plugin_job = gs_plugin_job_uninstall_apps_new (old_runtime_list, GS_PLUGIN_UNINSTALL_APPS_FLAGS_NONE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_true (ret);
/* remove the runtime */
g_assert_cmpstr (gs_app_get_unique_id (runtime), ==, "user/flatpak/test/org.test.Runtime/new_master");
g_object_unref (plugin_job);
runtime_list = gs_app_list_new ();
gs_app_list_add (runtime_list, runtime);
plugin_job = gs_plugin_job_uninstall_apps_new (runtime_list, GS_PLUGIN_UNINSTALL_APPS_FLAGS_NONE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_true (ret);
/* remove the remote */
g_object_unref (plugin_job);
plugin_job = gs_plugin_job_manage_repository_new (app_source, GS_PLUGIN_MANAGE_REPOSITORY_FLAGS_REMOVE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_true (ret);
g_assert_cmpint (gs_app_get_state (app_source), ==, GS_APP_STATE_UNAVAILABLE);
/* to not have deleted the "flatpak/tests/app-update/repo" content */
unlink (repo_path);
}
static void
gs_plugins_flatpak_runtime_extension_func (GsPluginLoader *plugin_loader)
{
GsApp *app;
GsApp *runtime;
GsApp *app_tmp;
gboolean got_progress_installing = FALSE;
gboolean ret;
guint notify_progress_id;
guint notify_state_id;
guint pending_app_changed_cnt = 0;
guint pending_apps_changed_id;
guint progress_cnt = 0;
guint updates_changed_cnt = 0;
guint updates_changed_id;
g_autofree gchar *repodir1_fn = NULL;
g_autofree gchar *repodir2_fn = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(GsApp) app_source = NULL;
g_autoptr(GsApp) extension = NULL;
g_autoptr(GsAppList) list = NULL;
g_autoptr(GsAppList) list_updates = NULL;
g_autoptr(GsPluginJob) plugin_job = NULL;
g_autoptr(GMainLoop) loop = g_main_loop_new (NULL, FALSE);
g_autofree gchar *repo_path = NULL;
g_autofree gchar *repo_url = NULL;
GsPlugin *plugin;
g_autoptr(GsAppQuery) query = NULL;
const gchar *keywords[2] = { NULL, };
g_autoptr(GsAppList) update_apps_list = NULL;
g_autoptr(GsAppList) runtime_list = NULL;
/* drop all caches */
gs_utils_rmtree (g_getenv ("GS_SELF_TEST_CACHEDIR"), NULL);
gs_test_reinitialise_plugin_loader (plugin_loader, allowlist, NULL);
/* no flatpak, abort */
g_assert_true (gs_plugin_loader_get_enabled (plugin_loader, "flatpak"));
/* no files to use */
repodir1_fn = gs_test_get_filename (TESTDATADIR, "app-extension/repo");
if (repodir1_fn == NULL ||
!g_file_test (repodir1_fn, G_FILE_TEST_EXISTS)) {
g_test_skip ("no flatpak test repo");
return;
}
repodir2_fn = gs_test_get_filename (TESTDATADIR, "app-extension-update/repo");
if (repodir2_fn == NULL ||
!g_file_test (repodir2_fn, G_FILE_TEST_EXISTS)) {
g_test_skip ("no flatpak test repo");
return;
}
/* add indirection so we can switch this after install */
repo_path = g_build_filename (g_getenv ("GS_SELF_TEST_FLATPAK_DATADIR"), "repo", NULL);
g_assert_cmpint (symlink (repodir1_fn, repo_path), ==, 0);
/* add a remote */
app_source = gs_flatpak_app_new ("test");
gs_app_set_kind (app_source, AS_COMPONENT_KIND_REPOSITORY);
plugin = gs_plugin_loader_find_plugin (plugin_loader, "flatpak");
gs_app_set_management_plugin (app_source, plugin);
gs_app_set_state (app_source, GS_APP_STATE_AVAILABLE);
repo_url = g_strdup_printf ("file://%s", repo_path);
gs_flatpak_app_set_repo_url (app_source, repo_url);
plugin_job = gs_plugin_job_manage_repository_new (app_source, GS_PLUGIN_MANAGE_REPOSITORY_FLAGS_INSTALL);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_true (ret);
g_assert_cmpint (gs_app_get_state (app_source), ==, GS_APP_STATE_INSTALLED);
/* refresh the appstream metadata */
g_object_unref (plugin_job);
plugin_job = gs_plugin_job_refresh_metadata_new (G_MAXUINT64,
GS_PLUGIN_REFRESH_METADATA_FLAGS_NONE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_true (ret);
/* find available application */
g_object_unref (plugin_job);
keywords[0] = "Bingo";
query = gs_app_query_new ("keywords", keywords,
"refine-flags", GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON,
"dedupe-flags", GS_PLUGIN_JOB_DEDUPE_FLAGS_DEFAULT,
"sort-func", gs_utils_app_sort_match_value,
NULL);
plugin_job = gs_plugin_job_list_apps_new (query, GS_PLUGIN_LIST_APPS_FLAGS_NONE);
g_clear_object (&query);
list = gs_plugin_loader_job_process (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_nonnull (list);
/* make sure there is one entry, the flatpak app */
g_assert_cmpint (gs_app_list_length (list), ==, 1);
app = gs_app_list_index (list, 0);
g_assert_cmpstr (gs_app_get_id (app), ==, "org.test.Chiron");
g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_AVAILABLE);
/* install, also installing runtime and suggested extensions */
g_object_unref (plugin_job);
plugin_job = gs_plugin_job_install_apps_new (list,
GS_PLUGIN_INSTALL_APPS_FLAGS_NONE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_true (ret);
g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_INSTALLED);
g_assert_cmpstr (gs_app_get_version (app), ==, "1.2.3");
/* check if the extension was installed */
extension = gs_plugin_loader_app_create (plugin_loader,
"user/flatpak/*/org.test.Chiron.Extension/master",
NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_nonnull (extension);
g_assert_cmpint (gs_app_get_state (extension), ==, GS_APP_STATE_INSTALLED);
/* switch to the new repo (to get the update) */
g_assert_cmpint (unlink (repo_path), ==, 0);
g_assert_cmpint (symlink (repodir2_fn, repo_path), ==, 0);
/* refresh the appstream metadata */
g_object_unref (plugin_job);
plugin_job = gs_plugin_job_refresh_metadata_new (0, /* force now */
GS_PLUGIN_REFRESH_METADATA_FLAGS_NONE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
g_assert_no_error (error);
g_assert_true (ret);
/* get the updates list */
g_object_unref (plugin_job);
query = gs_app_query_new ("is-for-update", GS_APP_QUERY_TRISTATE_TRUE,
"refine-flags", GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON |
GS_PLUGIN_REFINE_FLAGS_REQUIRE_UPDATE_DETAILS,
NULL);
plugin_job = gs_plugin_job_list_apps_new (query, GS_PLUGIN_LIST_APPS_FLAGS_NONE);
g_clear_object (&query);
list_updates = gs_plugin_loader_job_process (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_nonnull (list_updates);
g_assert_cmpint (gs_app_list_length (list_updates), ==, 1);
for (guint i = 0; i < gs_app_list_length (list_updates); i++) {
app_tmp = gs_app_list_index (list_updates, i);
g_debug ("got update %s", gs_app_get_unique_id (app_tmp));
}
/* check that the extension has no update */
app_tmp = gs_app_list_lookup (list_updates, "*/flatpak/test/org.test.Chiron.Extension/*");
g_assert_null (app_tmp);
/* check that the app has an update (it's affected by the extension's update) */
app = gs_app_list_lookup (list_updates, "*/flatpak/test/org.test.Chiron/*");
g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_UPDATABLE_LIVE);
/* care about signals */
pending_apps_changed_id =
g_signal_connect (plugin_loader, "pending-apps-changed",
G_CALLBACK (gs_plugins_flatpak_count_signal_cb),
&pending_app_changed_cnt);
updates_changed_id =
g_signal_connect (plugin_loader, "updates-changed",
G_CALLBACK (gs_plugins_flatpak_count_signal_cb),
&updates_changed_cnt);
notify_state_id =
g_signal_connect (app, "notify::state",
G_CALLBACK (update_app_state_notify_cb),
&got_progress_installing);
notify_progress_id =
g_signal_connect (app, "notify::progress",
G_CALLBACK (update_app_progress_notify_cb),
&progress_cnt);
/* use a mainloop so we get the events in the default context */
g_object_unref (plugin_job);
update_apps_list = gs_app_list_new ();
gs_app_list_add (update_apps_list, app);
plugin_job = gs_plugin_job_update_apps_new (update_apps_list, GS_PLUGIN_UPDATE_APPS_FLAGS_NO_DOWNLOAD);
gs_plugin_loader_job_process_async (plugin_loader, plugin_job,
NULL,
update_app_action_finish_sync,
loop);
g_main_loop_run (loop);
gs_test_flush_main_context ();
g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_INSTALLED);
g_assert_cmpstr (gs_app_get_version (app), ==, "1.2.3");
g_assert_true (got_progress_installing);
g_assert_cmpint (pending_app_changed_cnt, ==, 0);
/* The install refreshes GsApp-s cache, thus re-get the extension */
g_clear_object (&extension);
extension = gs_plugin_loader_app_create (plugin_loader,
"user/flatpak/*/org.test.Chiron.Extension/master",
NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_nonnull (extension);
/* check the extension's state after the update */
g_assert_cmpint (gs_app_get_state (extension), ==, GS_APP_STATE_INSTALLED);
/* no longer care */
g_signal_handler_disconnect (plugin_loader, pending_apps_changed_id);
g_signal_handler_disconnect (plugin_loader, updates_changed_id);
g_signal_handler_disconnect (app, notify_state_id);
g_signal_handler_disconnect (app, notify_progress_id);
g_clear_object (&list);
/* Reload the 'app', as it could change due to repo change */
g_object_unref (plugin_job);
keywords[0] = "Bingo";
query = gs_app_query_new ("keywords", keywords,
"refine-flags", GS_PLUGIN_REFINE_FLAGS_REQUIRE_RUNTIME,
"dedupe-flags", GS_PLUGIN_JOB_DEDUPE_FLAGS_DEFAULT,
"sort-func", gs_utils_app_sort_match_value,
NULL);
plugin_job = gs_plugin_job_list_apps_new (query, GS_PLUGIN_LIST_APPS_FLAGS_NONE);
g_clear_object (&query);
list = gs_plugin_loader_job_process (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_nonnull (list);
/* make sure there is one entry, the flatpak app */
g_assert_cmpint (gs_app_list_length (list), ==, 1);
app = gs_app_list_index (list, 0);
g_assert_cmpstr (gs_app_get_id (app), ==, "org.test.Chiron");
g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_INSTALLED);
/* getting the runtime for later removal */
runtime = gs_app_get_runtime (app);
g_assert_nonnull (runtime);
/* remove the app */
g_object_unref (plugin_job);
plugin_job = gs_plugin_job_uninstall_apps_new (list, GS_PLUGIN_UNINSTALL_APPS_FLAGS_NONE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
g_assert_no_error (error);
g_assert_true (ret);
/* remove the runtime */
g_object_unref (plugin_job);
runtime_list = gs_app_list_new ();
gs_app_list_add (runtime_list, runtime);
plugin_job = gs_plugin_job_uninstall_apps_new (runtime_list, GS_PLUGIN_UNINSTALL_APPS_FLAGS_NONE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_true (ret);
g_assert_cmpint (gs_app_get_state (runtime), ==, GS_APP_STATE_AVAILABLE);
/* remove the remote */
g_object_unref (plugin_job);
plugin_job = gs_plugin_job_manage_repository_new (app_source, GS_PLUGIN_MANAGE_REPOSITORY_FLAGS_REMOVE);
ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
gs_test_flush_main_context ();
g_assert_no_error (error);
g_assert_true (ret);
g_assert_cmpint (gs_app_get_state (app_source), ==, GS_APP_STATE_UNAVAILABLE);
/* verify that the extension has been removed by the app's removal */
g_assert_false (gs_app_is_installed (extension));
}
int
main (int argc, char **argv)
{
g_autofree gchar *tmp_root = NULL;
gboolean ret;
int retval;
g_autofree gchar *xml = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(GsPluginLoader) plugin_loader = NULL;
/* While we use %G_TEST_OPTION_ISOLATE_DIRS to create temporary directories
* for each of the tests, we want to use the system MIME registry, assuming
* that it exists and correctly has shared-mime-info installed. */
g_content_type_set_mime_dirs (NULL);
/* Similarly, add the system-wide icon theme path before its
* overwritten by %G_TEST_OPTION_ISOLATE_DIRS. */
gs_test_expose_icon_theme_paths ();
gs_test_init (&argc, &argv);
g_setenv ("GS_XMLB_VERBOSE", "1", TRUE);
g_setenv ("GS_SELF_TEST_PLUGIN_ERROR_FAIL_HARD", "1", TRUE);
/* Use a common cache directory for all tests, since the appstream
* plugin uses it and cannot be reinitialised for each test. */
tmp_root = g_dir_make_tmp ("gnome-software-flatpak-test-XXXXXX", NULL);
g_assert_true (tmp_root != NULL);
g_setenv ("GS_SELF_TEST_CACHEDIR", tmp_root, TRUE);
g_setenv ("GS_SELF_TEST_FLATPAK_DATADIR", tmp_root, TRUE);
/* allow dist'ing with no gnome-software installed */
if (g_getenv ("GS_SELF_TEST_SKIP_ALL") != NULL)
return 0;
xml = g_strdup ("<?xml version=\"1.0\"?>\n"
"<components version=\"0.9\">\n"
" <component type=\"desktop\">\n"
" <id>zeus.desktop</id>\n"
" <name>Zeus</name>\n"
" <summary>A teaching application</summary>\n"
" </component>\n"
"</components>\n");
g_setenv ("GS_SELF_TEST_APPSTREAM_XML", xml, TRUE);
/* we can only load this once per process */
plugin_loader = gs_plugin_loader_new (NULL, NULL);
gs_plugin_loader_add_location (plugin_loader, LOCALPLUGINDIR);
gs_plugin_loader_add_location (plugin_loader, LOCALPLUGINDIR_CORE);
ret = gs_plugin_loader_setup (plugin_loader,
allowlist,
NULL,
NULL,
&error);
g_assert_no_error (error);
g_assert_true (ret);
/* plugin tests go here */
g_test_add_data_func ("/gnome-software/plugins/flatpak/app-with-runtime",
plugin_loader,
(GTestDataFunc) gs_plugins_flatpak_app_with_runtime_func);
g_test_add_data_func ("/gnome-software/plugins/flatpak/app-missing-runtime",
plugin_loader,
(GTestDataFunc) gs_plugins_flatpak_app_missing_runtime_func);
g_test_add_data_func ("/gnome-software/plugins/flatpak/ref",
plugin_loader,
(GTestDataFunc) gs_plugins_flatpak_ref_func);
g_test_add_data_func ("/gnome-software/plugins/flatpak/bundle",
plugin_loader,
(GTestDataFunc) gs_plugins_flatpak_bundle_func);
g_test_add_data_func ("/gnome-software/plugins/flatpak/broken-remote",
plugin_loader,
(GTestDataFunc) gs_plugins_flatpak_broken_remote_func);
g_test_add_data_func ("/gnome-software/plugins/flatpak/runtime-repo",
plugin_loader,
(GTestDataFunc) gs_plugins_flatpak_runtime_repo_func);
g_test_add_data_func ("/gnome-software/plugins/flatpak/runtime-repo-redundant",
plugin_loader,
(GTestDataFunc) gs_plugins_flatpak_runtime_repo_redundant_func);
g_test_add_data_func ("/gnome-software/plugins/flatpak/app-runtime-extension",
plugin_loader,
(GTestDataFunc) gs_plugins_flatpak_runtime_extension_func);
g_test_add_data_func ("/gnome-software/plugins/flatpak/app-update-runtime",
plugin_loader,
(GTestDataFunc) gs_plugins_flatpak_app_update_func);
g_test_add_data_func ("/gnome-software/plugins/flatpak/repo",
plugin_loader,
(GTestDataFunc) gs_plugins_flatpak_repo_func);
g_test_add_data_func ("/gnome-software/plugins/flatpak/repo{non-ascii}",
plugin_loader,
(GTestDataFunc) gs_plugins_flatpak_repo_non_ascii_func);
retval = g_test_run ();
/* Clean up. */
gs_utils_rmtree (tmp_root, NULL);
return retval;
}