/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- * vi:set noexpandtab tabstop=8 shiftwidth=8: * * Copyright (C) 2013-2017 Richard Hughes * * SPDX-License-Identifier: GPL-2.0+ */ #include "config.h" #include #include #include "gnome-software-private.h" #include "gs-test.h" const gchar * const allowlist[] = { "appstream", "dummy", "generic-updates", "hardcoded-blocklist", "icons", "provenance", "provenance-license", NULL }; static guint _status_changed_cnt = 0; typedef struct { GError *error; GMainLoop *loop; } GsDummyTestHelper; static GsDummyTestHelper * gs_dummy_test_helper_new (void) { return g_new0 (GsDummyTestHelper, 1); } static void gs_dummy_test_helper_free (GsDummyTestHelper *helper) { if (helper->error != NULL) g_error_free (helper->error); if (helper->loop != NULL) g_main_loop_unref (helper->loop); g_free (helper); } G_DEFINE_AUTOPTR_CLEANUP_FUNC(GsDummyTestHelper, gs_dummy_test_helper_free) static void gs_plugin_loader_status_changed_cb (GsPluginLoader *plugin_loader, GsApp *app, GsPluginStatus status, gpointer user_data) { _status_changed_cnt++; } static void gs_plugins_dummy_install_func (GsPluginLoader *plugin_loader) { gboolean ret; g_autoptr(GsApp) app = NULL; g_autoptr(GsPluginJob) plugin_job = NULL; g_autoptr(GError) error = NULL; GsPlugin *plugin; /* install */ app = gs_app_new ("chiron.desktop"); plugin = gs_plugin_loader_find_plugin (plugin_loader, "dummy"); gs_app_set_management_plugin (app, plugin); gs_app_set_state (app, GS_APP_STATE_AVAILABLE); plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_INSTALL, "app", app, NULL); ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error); gs_test_flush_main_context (); g_assert_no_error (error); g_assert (ret); g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_INSTALLED); /* remove */ g_object_unref (plugin_job); plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_REMOVE, "app", app, NULL); ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error); gs_test_flush_main_context (); g_assert_no_error (error); g_assert (ret); g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_AVAILABLE); } static void gs_plugins_dummy_error_func (GsPluginLoader *plugin_loader) { const GError *app_error; gboolean ret; g_autoptr(GError) error = NULL; g_autoptr(GPtrArray) events = NULL; g_autoptr(GsApp) app = NULL; g_autoptr(GsPluginEvent) event = 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); /* update, which should cause an error to be emitted */ app = gs_app_new ("chiron.desktop"); plugin = gs_plugin_loader_find_plugin (plugin_loader, "dummy"); gs_app_set_management_plugin (app, plugin); gs_app_set_state (app, GS_APP_STATE_AVAILABLE); plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_UPDATE, "app", app, NULL); ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error); gs_test_flush_main_context (); g_assert_no_error (error); g_assert (ret); /* get last active event */ event = gs_plugin_loader_get_event_default (plugin_loader); g_assert (event != NULL); g_assert (gs_plugin_event_get_app (event) == app); /* check all the events */ events = gs_plugin_loader_get_events (plugin_loader); g_assert_cmpint (events->len, ==, 1); event = g_ptr_array_index (events, 0); g_assert (gs_plugin_event_get_app (event) == app); app_error = gs_plugin_event_get_error (event); g_assert (app_error != NULL); g_assert_error (app_error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_DOWNLOAD_FAILED); } static void gs_plugins_dummy_refine_func (GsPluginLoader *plugin_loader) { gboolean ret; g_autoptr(GsApp) app = NULL; g_autoptr(GError) error = NULL; g_autoptr(GsPluginJob) plugin_job = NULL; GsPlugin *plugin; /* get the extra bits */ app = gs_app_new ("chiron.desktop"); plugin = gs_plugin_loader_find_plugin (plugin_loader, "dummy"); gs_app_set_management_plugin (app, plugin); plugin_job = gs_plugin_job_refine_new_for_app (app, GS_PLUGIN_REFINE_FLAGS_REQUIRE_DESCRIPTION | GS_PLUGIN_REFINE_FLAGS_REQUIRE_LICENSE | GS_PLUGIN_REFINE_FLAGS_REQUIRE_URL); ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error); gs_test_flush_main_context (); g_assert_no_error (error); g_assert (ret); g_assert_cmpstr (gs_app_get_license (app), ==, "GPL-2.0+"); g_assert_cmpstr (gs_app_get_description (app), !=, NULL); g_assert_cmpstr (gs_app_get_url (app, AS_URL_KIND_HOMEPAGE), ==, "http://www.test.org/"); } static void gs_plugins_dummy_metadata_quirks (GsPluginLoader *plugin_loader) { gboolean ret; g_autoptr(GsApp) app = NULL; g_autoptr(GError) error = NULL; g_autoptr(GsPluginJob) plugin_job = NULL; GsPlugin *plugin; /* get the extra bits */ app = gs_app_new ("chiron.desktop"); plugin = gs_plugin_loader_find_plugin (plugin_loader, "dummy"); gs_app_set_management_plugin (app, plugin); plugin_job = gs_plugin_job_refine_new_for_app (app, GS_PLUGIN_REFINE_FLAGS_REQUIRE_DESCRIPTION); ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error); gs_test_flush_main_context (); g_assert_no_error (error); g_assert (ret); g_assert_cmpstr (gs_app_get_description (app), !=, NULL); /* check the not-launchable quirk */ g_assert (!gs_app_has_quirk(app, GS_APP_QUIRK_NOT_LAUNCHABLE)); gs_app_set_metadata (app, "GnomeSoftware::quirks::not-launchable", "true"); g_object_unref (plugin_job); plugin_job = gs_plugin_job_refine_new_for_app (app, GS_PLUGIN_REFINE_FLAGS_REQUIRE_DESCRIPTION); ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error); gs_test_flush_main_context (); g_assert_no_error (error); g_assert (ret); g_assert (gs_app_has_quirk(app, GS_APP_QUIRK_NOT_LAUNCHABLE)); gs_app_set_metadata (app, "GnomeSoftware::quirks::not-launchable", NULL); gs_app_set_metadata (app, "GnomeSoftware::quirks::not-launchable", "false"); g_object_unref (plugin_job); plugin_job = gs_plugin_job_refine_new_for_app (app, GS_PLUGIN_REFINE_FLAGS_REQUIRE_DESCRIPTION); ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error); gs_test_flush_main_context (); g_assert_no_error (error); g_assert (ret); g_assert (!gs_app_has_quirk(app, GS_APP_QUIRK_NOT_LAUNCHABLE)); } static void gs_plugins_dummy_key_colors_func (GsPluginLoader *plugin_loader) { GArray *array; gboolean ret; guint i; g_autoptr(GsApp) app = NULL; g_autoptr(GsPluginJob) plugin_job = NULL; g_autoptr(GError) error = NULL; /* get the extra bits */ app = gs_app_new ("chiron.desktop"); plugin_job = gs_plugin_job_refine_new_for_app (app, GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON); ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error); gs_test_flush_main_context (); g_assert_no_error (error); g_assert (ret); array = gs_app_get_key_colors (app); g_assert_cmpint (array->len, <=, 3); g_assert_cmpint (array->len, >, 0); /* check values are in range */ for (i = 0; i < array->len; i++) { const GdkRGBA *kc = &g_array_index (array, GdkRGBA, i); g_assert_cmpfloat (kc->red, >=, 0.f); g_assert_cmpfloat (kc->red, <=, 1.f); g_assert_cmpfloat (kc->green, >=, 0.f); g_assert_cmpfloat (kc->green, <=, 1.f); g_assert_cmpfloat (kc->blue, >=, 0.f); g_assert_cmpfloat (kc->blue, <=, 1.f); g_assert_cmpfloat (kc->alpha, >=, 0.f); g_assert_cmpfloat (kc->alpha, <=, 1.f); } } static void gs_plugins_dummy_updates_func (GsPluginLoader *plugin_loader) { GsApp *app; g_autoptr(GError) error = NULL; g_autoptr(GsAppList) list = NULL; g_autoptr(GsPluginJob) plugin_job = NULL; /* get the updates list */ plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_GET_UPDATES, "refine-flags", GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON | GS_PLUGIN_REFINE_FLAGS_REQUIRE_UPDATE_DETAILS, NULL); list = gs_plugin_loader_job_process (plugin_loader, plugin_job, NULL, &error); gs_test_flush_main_context (); g_assert_no_error (error); g_assert (list != NULL); /* make sure there are three entries */ g_assert_cmpint (gs_app_list_length (list), ==, 3); app = gs_app_list_index (list, 0); g_assert_cmpstr (gs_app_get_id (app), ==, "chiron.desktop"); g_assert_cmpint (gs_app_get_kind (app), ==, AS_COMPONENT_KIND_DESKTOP_APP); g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_UPDATABLE_LIVE); g_assert_cmpstr (gs_app_get_update_details_markup (app), ==, "Do not crash when using libvirt."); g_assert_cmpint (gs_app_get_update_urgency (app), ==, AS_URGENCY_KIND_HIGH); /* get the virtual non-apps OS update */ app = gs_app_list_index (list, 2); g_assert_cmpstr (gs_app_get_id (app), ==, "org.gnome.Software.OsUpdate"); g_assert_cmpstr (gs_app_get_name (app), ==, "System Updates"); g_assert_cmpstr (gs_app_get_summary (app), ==, "General system updates, such as security or bug fixes, and performance improvements."); g_assert_cmpint (gs_app_get_kind (app), ==, AS_COMPONENT_KIND_GENERIC); g_assert_cmpint (gs_app_get_special_kind (app), ==, GS_APP_SPECIAL_KIND_OS_UPDATE); g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_UPDATABLE); g_assert_cmpint (gs_app_list_length (gs_app_get_related (app)), ==, 2); /* get the virtual non-apps OS update */ app = gs_app_list_index (list, 1); g_assert_cmpstr (gs_app_get_id (app), ==, "proxy.desktop"); g_assert (gs_app_has_quirk (app, GS_APP_QUIRK_IS_PROXY)); g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_UPDATABLE_LIVE); g_assert_cmpint (gs_app_list_length (gs_app_get_related (app)), ==, 2); } static void gs_plugins_dummy_distro_upgrades_func (GsPluginLoader *plugin_loader) { GsApp *app; gboolean ret; g_autoptr(GError) error = NULL; g_autoptr(GsAppList) list = NULL; g_autoptr(GsPluginJob) plugin_job = NULL; /* get the updates list */ plugin_job = gs_plugin_job_list_distro_upgrades_new (GS_PLUGIN_LIST_DISTRO_UPGRADES_FLAGS_NONE, GS_PLUGIN_REFINE_FLAGS_NONE); list = gs_plugin_loader_job_process (plugin_loader, plugin_job, NULL, &error); gs_test_flush_main_context (); g_assert_no_error (error); g_assert (list != NULL); /* make sure there is one entry */ 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.fedoraproject.release-rawhide.upgrade"); g_assert_cmpint (gs_app_get_kind (app), ==, AS_COMPONENT_KIND_OPERATING_SYSTEM); g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_AVAILABLE); /* this should be set with a higher priority by AppStream */ g_assert_cmpstr (gs_app_get_summary (app), ==, "Release specific tagline"); /* download the update */ g_object_unref (plugin_job); plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_UPGRADE_DOWNLOAD, "app", app, NULL); ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error); gs_test_flush_main_context (); g_assert_no_error (error); g_assert (ret); g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_UPDATABLE); /* trigger the update */ g_object_unref (plugin_job); plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_UPGRADE_TRIGGER, "app", app, NULL); ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error); gs_test_flush_main_context (); g_assert_no_error (error); g_assert (ret); g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_UPDATABLE); } static gboolean filter_valid_cb (GsApp *app, gpointer user_data) { return gs_plugin_loader_app_is_valid (app, GS_PLUGIN_REFINE_FLAGS_NONE); } static void gs_plugins_dummy_installed_func (GsPluginLoader *plugin_loader) { GsApp *app; GsApp *addon; g_autoptr(GsAppList) addons = NULL; g_autofree gchar *menu_path = NULL; g_autoptr(GError) error = NULL; g_autoptr(GsAppList) list = NULL; g_autoptr(GsAppQuery) query = NULL; g_autoptr(GsPluginJob) plugin_job = NULL; g_autoptr(GIcon) icon = NULL; GsPluginRefineFlags refine_flags; /* get installed packages */ refine_flags = (GS_PLUGIN_REFINE_FLAGS_REQUIRE_ORIGIN | GS_PLUGIN_REFINE_FLAGS_REQUIRE_ADDONS | GS_PLUGIN_REFINE_FLAGS_REQUIRE_LICENSE | GS_PLUGIN_REFINE_FLAGS_REQUIRE_KUDOS | GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON | GS_PLUGIN_REFINE_FLAGS_REQUIRE_CATEGORIES | GS_PLUGIN_REFINE_FLAGS_REQUIRE_PROVENANCE); query = gs_app_query_new ("is-installed", GS_APP_QUERY_TRISTATE_TRUE, "refine-flags", refine_flags, "dedupe-flags", GS_PLUGIN_JOB_DEDUPE_FLAGS_DEFAULT, "filter-func", filter_valid_cb, NULL); plugin_job = gs_plugin_job_list_apps_new (query, GS_PLUGIN_LIST_APPS_FLAGS_NONE); list = gs_plugin_loader_job_process (plugin_loader, plugin_job, NULL, &error); gs_test_flush_main_context (); g_assert_no_error (error); g_assert (list != NULL); /* make sure there is one entry */ g_assert_cmpint (gs_app_list_length (list), ==, 1); app = gs_app_list_index (list, 0); g_assert_cmpstr (gs_app_get_id (app), ==, "zeus.desktop"); g_assert_cmpint (gs_app_get_kind (app), ==, AS_COMPONENT_KIND_DESKTOP_APP); g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_INSTALLED); g_assert_cmpstr (gs_app_get_name (app), ==, "Zeus"); g_assert_cmpstr (gs_app_get_source_default (app), ==, "zeus"); icon = gs_app_get_icon_for_size (app, 48, 1, NULL); g_assert_nonnull (icon); g_clear_object (&icon); /* check various bitfields */ g_assert (gs_app_has_quirk (app, GS_APP_QUIRK_PROVENANCE)); g_assert_cmpstr (gs_app_get_license (app), ==, "GPL-2.0+"); g_assert (gs_app_get_license_is_free (app)); /* check kudos */ g_assert_true (gs_app_has_kudo (app, GS_APP_KUDO_MY_LANGUAGE)); /* check categories */ g_assert (gs_app_has_category (app, "Player")); g_assert (gs_app_has_category (app, "AudioVideo")); g_assert (!gs_app_has_category (app, "ImageProcessing")); g_assert (gs_app_get_menu_path (app) != NULL); menu_path = g_strjoinv ("->", gs_app_get_menu_path (app)); g_assert_cmpstr (menu_path, ==, "Create->Music Players"); /* check addon */ addons = gs_app_dup_addons (app); g_assert_nonnull (addons); g_assert_cmpint (gs_app_list_length (addons), ==, 1); addon = gs_app_list_index (addons, 0); g_assert_cmpstr (gs_app_get_id (addon), ==, "zeus-spell.addon"); g_assert_cmpint (gs_app_get_kind (addon), ==, AS_COMPONENT_KIND_ADDON); g_assert_cmpint (gs_app_get_state (addon), ==, GS_APP_STATE_AVAILABLE); g_assert_cmpstr (gs_app_get_name (addon), ==, "Spell Check"); g_assert_cmpstr (gs_app_get_source_default (addon), ==, "zeus-spell"); g_assert_cmpstr (gs_app_get_license (addon), ==, "LicenseRef-free=https://www.debian.org/"); icon = gs_app_get_icon_for_size (addon, 48, 1, NULL); g_assert_null (icon); } static void gs_plugins_dummy_search_func (GsPluginLoader *plugin_loader) { GsApp *app; g_autoptr(GError) error = NULL; g_autoptr(GsAppList) list = NULL; g_autoptr(GsPluginJob) plugin_job = NULL; g_autoptr(GsAppQuery) query = NULL; const gchar *keywords[2] = { NULL, }; /* get search result based on addon keyword */ keywords[0] = "zeus"; 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); list = gs_plugin_loader_job_process (plugin_loader, plugin_job, NULL, &error); gs_test_flush_main_context (); g_assert_no_error (error); g_assert (list != NULL); /* make sure there is at least one entry, the parent app, which must be first */ g_assert_cmpint (gs_app_list_length (list), >=, 1); app = gs_app_list_index (list, 0); g_assert_cmpstr (gs_app_get_id (app), ==, "zeus.desktop"); g_assert_cmpint (gs_app_get_kind (app), ==, AS_COMPONENT_KIND_DESKTOP_APP); } static void gs_plugins_dummy_search_alternate_func (GsPluginLoader *plugin_loader) { GsApp *app_tmp; g_autoptr(GError) error = NULL; g_autoptr(GsAppList) list = NULL; g_autoptr(GsApp) app = NULL; g_autoptr(GsAppQuery) query = NULL; g_autoptr(GsPluginJob) plugin_job = NULL; /* get search result based on addon keyword */ app = gs_app_new ("zeus.desktop"); query = gs_app_query_new ("alternate-of", app, "refine-flags", GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON, "dedupe-flags", GS_PLUGIN_JOB_DEDUPE_FLAGS_DEFAULT, "sort-func", gs_utils_app_sort_priority, NULL); plugin_job = gs_plugin_job_list_apps_new (query, GS_PLUGIN_LIST_APPS_FLAGS_NONE); list = gs_plugin_loader_job_process (plugin_loader, plugin_job, NULL, &error); gs_test_flush_main_context (); g_assert_no_error (error); g_assert (list != NULL); /* make sure there is the original app, and the alternate */ g_assert_cmpint (gs_app_list_length (list), ==, 2); app_tmp = gs_app_list_index (list, 0); g_assert_cmpstr (gs_app_get_id (app_tmp), ==, "chiron.desktop"); g_assert_cmpint (gs_app_get_kind (app_tmp), ==, AS_COMPONENT_KIND_DESKTOP_APP); app_tmp = gs_app_list_index (list, 1); g_assert_cmpstr (gs_app_get_id (app_tmp), ==, "zeus.desktop"); g_assert_cmpint (gs_app_get_kind (app_tmp), ==, AS_COMPONENT_KIND_DESKTOP_APP); } static void gs_plugins_dummy_url_to_app_func (GsPluginLoader *plugin_loader) { g_autoptr(GError) error = NULL; g_autoptr(GsApp) app = NULL; g_autoptr(GsPluginJob) plugin_job = NULL; plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_URL_TO_APP, "search", "dummy://chiron.desktop", "refine-flags", GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON, NULL); 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 (app != NULL); g_assert_cmpstr (gs_app_get_id (app), ==, "chiron.desktop"); g_assert_cmpint (gs_app_get_kind (app), ==, AS_COMPONENT_KIND_DESKTOP_APP); } static void gs_plugins_dummy_plugin_cache_func (GsPluginLoader *plugin_loader) { GsApp *app1; GsApp *app2; g_autoptr(GError) error = NULL; g_autoptr(GsAppList) list1 = NULL; g_autoptr(GsAppList) list2 = NULL; g_autoptr(GsPluginJob) plugin_job = NULL; /* ensure we get the same results back from calling the methods twice */ plugin_job = gs_plugin_job_list_distro_upgrades_new (GS_PLUGIN_LIST_DISTRO_UPGRADES_FLAGS_NONE, GS_PLUGIN_REFINE_FLAGS_NONE); list1 = gs_plugin_loader_job_process (plugin_loader, plugin_job, NULL, &error); gs_test_flush_main_context (); g_assert_no_error (error); g_assert (list1 != NULL); g_assert_cmpint (gs_app_list_length (list1), ==, 1); app1 = gs_app_list_index (list1, 0); g_object_unref (plugin_job); plugin_job = gs_plugin_job_list_distro_upgrades_new (GS_PLUGIN_LIST_DISTRO_UPGRADES_FLAGS_NONE, GS_PLUGIN_REFINE_FLAGS_NONE); list2 = gs_plugin_loader_job_process (plugin_loader, plugin_job, NULL, &error); gs_test_flush_main_context (); g_assert_no_error (error); g_assert (list2 != NULL); g_assert_cmpint (gs_app_list_length (list2), ==, 1); app2 = gs_app_list_index (list2, 0); /* make sure there is one GObject */ g_assert_cmpstr (gs_app_get_id (app1), ==, gs_app_get_id (app2)); g_assert (app1 == app2); } static void gs_plugins_dummy_wildcard_func (GsPluginLoader *plugin_loader) { g_autoptr(GError) error = NULL; g_autoptr(GsAppList) list1 = NULL; g_autoptr(GsAppList) list2 = NULL; const gchar *expected_apps2[] = { "chiron.desktop", "zeus.desktop", NULL }; g_autoptr(GsPluginJob) plugin_job = NULL; g_autoptr(GsAppQuery) query = NULL; /* use the plugin's default curated list, indicated by setting max-results=5 */ query = gs_app_query_new ("is-curated", GS_APP_QUERY_TRISTATE_TRUE, "max-results", 5, "refine-flags", GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON, NULL); plugin_job = gs_plugin_job_list_apps_new (query, GS_PLUGIN_LIST_APPS_FLAGS_NONE); list1 = gs_plugin_loader_job_process (plugin_loader, plugin_job, NULL, &error); gs_test_flush_main_context (); g_assert_no_error (error); g_assert (list1 != NULL); g_assert_cmpint (gs_app_list_length (list1), ==, 1); g_object_unref (plugin_job); g_object_unref (query); /* use the plugin’s second list, indicated by setting max-results=6 */ query = gs_app_query_new ("is-curated", GS_APP_QUERY_TRISTATE_TRUE, "max-results", 6, "refine-flags", GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON, NULL); plugin_job = gs_plugin_job_list_apps_new (query, GS_PLUGIN_LIST_APPS_FLAGS_NONE); list2 = gs_plugin_loader_job_process (plugin_loader, plugin_job, NULL, &error); gs_test_flush_main_context (); g_assert_no_error (error); g_assert (list2 != NULL); g_assert_cmpint (gs_app_list_length (list2), ==, g_strv_length ((gchar **) expected_apps2)); for (guint i = 0; i < gs_app_list_length (list2); ++i) { GsApp *app = gs_app_list_index (list2, i); g_assert (g_strv_contains (expected_apps2, gs_app_get_id (app))); } } static void plugin_job_action_cb (GObject *source, GAsyncResult *res, gpointer user_data) { GsPluginLoader *plugin_loader = GS_PLUGIN_LOADER (source); GsDummyTestHelper *helper = (GsDummyTestHelper *) user_data; gs_plugin_loader_job_action_finish (plugin_loader, res, &helper->error); if (helper->loop != NULL) g_main_loop_quit (helper->loop); } static void gs_plugins_dummy_limit_parallel_ops_func (GsPluginLoader *plugin_loader) { g_autoptr(GsAppList) list = NULL; GsApp *app1 = NULL; g_autoptr(GsApp) app2 = NULL; g_autoptr(GsApp) app3 = NULL; GsPlugin *plugin; g_autoptr(GsPluginJob) plugin_job1 = NULL; g_autoptr(GsPluginJob) plugin_job2 = NULL; g_autoptr(GsPluginJob) plugin_job3 = NULL; g_autoptr(GMainContext) context = NULL; g_autoptr(GsDummyTestHelper) helper1 = gs_dummy_test_helper_new (); g_autoptr(GsDummyTestHelper) helper2 = gs_dummy_test_helper_new (); g_autoptr(GsDummyTestHelper) helper3 = gs_dummy_test_helper_new (); /* drop all caches */ gs_utils_rmtree (g_getenv ("GS_SELF_TEST_CACHEDIR"), NULL); gs_test_reinitialise_plugin_loader (plugin_loader, allowlist, NULL); /* get the updates list */ plugin_job1 = gs_plugin_job_list_distro_upgrades_new (GS_PLUGIN_LIST_DISTRO_UPGRADES_FLAGS_NONE, GS_PLUGIN_REFINE_FLAGS_NONE); list = gs_plugin_loader_job_process (plugin_loader, plugin_job1, NULL, &helper3->error); gs_test_flush_main_context (); g_assert_no_error (helper3->error); g_assert (list != NULL); g_assert_cmpint (gs_app_list_length (list), ==, 1); app1 = gs_app_list_index (list, 0); g_assert_cmpstr (gs_app_get_id (app1), ==, "org.fedoraproject.release-rawhide.upgrade"); g_assert_cmpint (gs_app_get_kind (app1), ==, AS_COMPONENT_KIND_OPERATING_SYSTEM); g_assert_cmpint (gs_app_get_state (app1), ==, GS_APP_STATE_AVAILABLE); /* allow only one operation at a time */ gs_plugin_loader_set_max_parallel_ops (plugin_loader, 1); app2 = gs_app_new ("chiron.desktop"); plugin = gs_plugin_loader_find_plugin (plugin_loader, "dummy"); gs_app_set_management_plugin (app2, plugin); gs_app_set_state (app2, GS_APP_STATE_AVAILABLE); /* use "proxy" prefix so the update function succeeds... */ app3 = gs_app_new ("proxy-zeus.desktop"); gs_app_set_management_plugin (app3, plugin); gs_app_set_state (app3, GS_APP_STATE_UPDATABLE_LIVE); context = g_main_context_new (); helper3->loop = g_main_loop_new (context, FALSE); g_main_context_push_thread_default (context); /* call a few operations at the "same time" */ /* download an upgrade */ g_object_unref (plugin_job1); plugin_job1 = gs_plugin_job_newv (GS_PLUGIN_ACTION_UPGRADE_DOWNLOAD, "app", app1, NULL); gs_plugin_loader_job_process_async (plugin_loader, plugin_job1, NULL, plugin_job_action_cb, helper1); /* install an app */ plugin_job2 = gs_plugin_job_newv (GS_PLUGIN_ACTION_INSTALL, "app", app2, NULL); gs_plugin_loader_job_process_async (plugin_loader, plugin_job2, NULL, plugin_job_action_cb, helper2); /* update an app */ plugin_job3 = gs_plugin_job_newv (GS_PLUGIN_ACTION_UPDATE, "app", app3, NULL); gs_plugin_loader_job_process_async (plugin_loader, plugin_job3, NULL, plugin_job_action_cb, helper3); /* since we have only 1 parallel installation op possible, * verify the last operations are pending */ g_assert_cmpint (gs_app_get_state (app2), ==, GS_APP_STATE_QUEUED_FOR_INSTALL); g_assert_cmpint (gs_app_get_pending_action (app2), ==, GS_PLUGIN_ACTION_INSTALL); g_assert_cmpint (gs_app_get_state (app3), ==, GS_APP_STATE_UPDATABLE_LIVE); g_assert_cmpint (gs_app_get_pending_action (app3), ==, GS_PLUGIN_ACTION_UPDATE); /* wait for the 2nd installation to finish, it means the 1st should have been * finished too */ g_main_loop_run (helper3->loop); g_main_context_pop_thread_default (context); gs_test_flush_main_context (); g_assert_no_error (helper1->error); g_assert_no_error (helper2->error); g_assert_no_error (helper3->error); g_assert_cmpint (gs_app_get_state (app1), ==, GS_APP_STATE_UPDATABLE); g_assert_cmpint (gs_app_get_state (app2), ==, GS_APP_STATE_INSTALLED); g_assert_cmpint (gs_app_get_state (app3), ==, GS_APP_STATE_INSTALLED); /* set the default max parallel ops */ gs_plugin_loader_set_max_parallel_ops (plugin_loader, 0); } static void gs_plugins_dummy_app_size_calc_func (GsPluginLoader *loader) { g_autoptr(GsApp) app1 = NULL; g_autoptr(GsApp) app2 = NULL; g_autoptr(GsApp) runtime = NULL; guint64 value = 0; app1 = gs_app_new ("app1"); gs_app_set_state (app1, GS_APP_STATE_AVAILABLE); gs_app_set_size_download (app1, GS_SIZE_TYPE_VALID, 1); gs_app_set_size_installed (app1, GS_SIZE_TYPE_VALID, 1000); g_assert_cmpint (gs_app_get_size_download (app1, &value), ==, GS_SIZE_TYPE_VALID); g_assert_cmpint (value, ==, 1); g_assert_cmpint (gs_app_get_size_download_dependencies (app1, &value), ==, GS_SIZE_TYPE_VALID); g_assert_cmpint (value, ==, 0); g_assert_cmpint (gs_app_get_size_installed (app1, &value), ==, GS_SIZE_TYPE_VALID); g_assert_cmpint (value, ==, 1000); g_assert_cmpint (gs_app_get_size_installed_dependencies (app1, &value), ==, GS_SIZE_TYPE_VALID); g_assert_cmpint (value, ==, 0); app2 = gs_app_new ("app2"); gs_app_set_state (app2, GS_APP_STATE_AVAILABLE); gs_app_set_size_download (app2, GS_SIZE_TYPE_VALID, 20); gs_app_set_size_installed (app2, GS_SIZE_TYPE_VALID, 20000); g_assert_cmpint (gs_app_get_size_download (app2, &value), ==, GS_SIZE_TYPE_VALID); g_assert_cmpint (value, ==, 20); g_assert_cmpint (gs_app_get_size_download_dependencies (app2, &value), ==, GS_SIZE_TYPE_VALID); g_assert_cmpint (value, ==, 0); g_assert_cmpint (gs_app_get_size_installed (app2, &value), ==, GS_SIZE_TYPE_VALID); g_assert_cmpint (value, ==, 20000); g_assert_cmpint (gs_app_get_size_installed_dependencies (app2, &value), ==, GS_SIZE_TYPE_VALID); g_assert_cmpint (value, ==, 0); runtime = gs_app_new ("runtime"); gs_app_set_state (runtime, GS_APP_STATE_AVAILABLE); gs_app_set_size_download (runtime, GS_SIZE_TYPE_VALID, 300); gs_app_set_size_installed (runtime, GS_SIZE_TYPE_VALID, 300000); g_assert_cmpint (gs_app_get_size_download (runtime, &value), ==, GS_SIZE_TYPE_VALID); g_assert_cmpint (value, ==, 300); g_assert_cmpint (gs_app_get_size_download_dependencies (runtime, &value), ==, GS_SIZE_TYPE_VALID); g_assert_cmpint (value, ==, 0); g_assert_cmpint (gs_app_get_size_installed (runtime, &value), ==, GS_SIZE_TYPE_VALID); g_assert_cmpint (value, ==, 300000); g_assert_cmpint (gs_app_get_size_installed_dependencies (runtime, &value), ==, GS_SIZE_TYPE_VALID); g_assert_cmpint (value, ==, 0); gs_app_set_runtime (app1, runtime); g_assert_cmpint (gs_app_get_size_download (app1, &value), ==, GS_SIZE_TYPE_VALID); g_assert_cmpint (value, ==, 1); g_assert_cmpint (gs_app_get_size_download_dependencies (app1, &value), ==, GS_SIZE_TYPE_VALID); g_assert_cmpint (value, ==, 300); g_assert_cmpint (gs_app_get_size_installed (app1, &value), ==, GS_SIZE_TYPE_VALID); g_assert_cmpint (value, ==, 1000); g_assert_cmpint (gs_app_get_size_installed_dependencies (app1, &value), ==, GS_SIZE_TYPE_VALID); g_assert_cmpint (value, ==, 0); gs_app_set_runtime (app2, runtime); g_assert_cmpint (gs_app_get_size_download (app2, &value), ==, GS_SIZE_TYPE_VALID); g_assert_cmpint (value, ==, 20); g_assert_cmpint (gs_app_get_size_download_dependencies (app2, &value), ==, GS_SIZE_TYPE_VALID); g_assert_cmpint (value, ==, 300); g_assert_cmpint (gs_app_get_size_installed (app2, &value), ==, GS_SIZE_TYPE_VALID); g_assert_cmpint (value, ==, 20000); g_assert_cmpint (gs_app_get_size_installed_dependencies (app2, &value), ==, GS_SIZE_TYPE_VALID); g_assert_cmpint (value, ==, 0); gs_app_add_related (app1, app2); g_assert_cmpint (gs_app_get_size_download (app1, &value), ==, GS_SIZE_TYPE_VALID); g_assert_cmpint (value, ==, 1); g_assert_cmpint (gs_app_get_size_download_dependencies (app1, &value), ==, GS_SIZE_TYPE_VALID); g_assert_cmpint (value, ==, 320); g_assert_cmpint (gs_app_get_size_installed (app1, &value), ==, GS_SIZE_TYPE_VALID); g_assert_cmpint (value, ==, 1000); g_assert_cmpint (gs_app_get_size_installed_dependencies (app1, &value), ==, GS_SIZE_TYPE_VALID); g_assert_cmpint (value, ==, 20000); g_assert_cmpint (gs_app_get_size_download (app2, &value), ==, GS_SIZE_TYPE_VALID); g_assert_cmpint (value, ==, 20); g_assert_cmpint (gs_app_get_size_download_dependencies (app2, &value), ==, GS_SIZE_TYPE_VALID); g_assert_cmpint (value, ==, 300); g_assert_cmpint (gs_app_get_size_installed (app2, &value), ==, GS_SIZE_TYPE_VALID); g_assert_cmpint (value, ==, 20000); g_assert_cmpint (gs_app_get_size_installed_dependencies (app2, &value), ==, GS_SIZE_TYPE_VALID); g_assert_cmpint (value, ==, 0); } 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); /* Force the GTK resources to be registered, needed for fallback icons. */ gtk_init_check (); /* Similarly, add the system-wide icon theme path before it’s * 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); /* set all the things required as a dummy test harness */ setlocale (LC_MESSAGES, "en_GB.UTF-8"); g_setenv ("GS_SELF_TEST_DUMMY_ENABLE", "1", TRUE); g_setenv ("GS_SELF_TEST_PROVENANCE_SOURCES", "london*,boston", TRUE); g_setenv ("GS_SELF_TEST_PROVENANCE_LICENSE_SOURCES", "london*,boston", TRUE); g_setenv ("GS_SELF_TEST_PROVENANCE_LICENSE_URL", "https://www.debian.org/", 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-dummy-test-XXXXXX", NULL); g_assert (tmp_root != NULL); g_setenv ("GS_SELF_TEST_CACHEDIR", tmp_root, TRUE); xml = g_strdup ("\n" "\n" " \n" " chiron.desktop\n" " Chiron\n" " chiron\n" " \n" " \n" " zeus.desktop\n" " Zeus\n" " A teaching application\n" " zeus\n" " drive-harddisk\n" " \n" " AudioVideo\n" " Player\n" " \n" " \n" " en_GB\n" " \n" " \n" " \n" " mate-spell.desktop\n" " Spell\n" " A spelling application for MATE\n" " mate-spell\n" " drive-harddisk\n" " MATE\n" " \n" " \n" " zeus-spell.addon\n" " zeus.desktop\n" " Spell Check\n" " Check the spelling when teaching\n" " zeus-spell\n" " \n" " \n" " Uninstall Zeus.desktop\n" " Uninstall Zeus\n" " Uninstall the teaching application\n" " drive-harddisk\n" " \n" " \n" " org.fedoraproject.release-rawhide.upgrade\n" " Fedora Rawhide\n" " Release specific tagline\n" " fedora-release\n" " \n" " \n" " user\n" " \n" "\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); g_signal_connect (plugin_loader, "status-changed", G_CALLBACK (gs_plugin_loader_status_changed_cb), 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 (ret); g_assert (!gs_plugin_loader_get_enabled (plugin_loader, "notgoingtoexist")); g_assert (gs_plugin_loader_get_enabled (plugin_loader, "appstream")); g_assert (gs_plugin_loader_get_enabled (plugin_loader, "dummy")); /* plugin tests go here */ g_test_add_data_func ("/gnome-software/plugins/dummy/wildcard", plugin_loader, (GTestDataFunc) gs_plugins_dummy_wildcard_func); g_test_add_data_func ("/gnome-software/plugins/dummy/plugin-cache", plugin_loader, (GTestDataFunc) gs_plugins_dummy_plugin_cache_func); g_test_add_data_func ("/gnome-software/plugins/dummy/key-colors", plugin_loader, (GTestDataFunc) gs_plugins_dummy_key_colors_func); g_test_add_data_func ("/gnome-software/plugins/dummy/search", plugin_loader, (GTestDataFunc) gs_plugins_dummy_search_func); g_test_add_data_func ("/gnome-software/plugins/dummy/search-alternate", plugin_loader, (GTestDataFunc) gs_plugins_dummy_search_alternate_func); g_test_add_data_func ("/gnome-software/plugins/dummy/url-to-app", plugin_loader, (GTestDataFunc) gs_plugins_dummy_url_to_app_func); g_test_add_data_func ("/gnome-software/plugins/dummy/install", plugin_loader, (GTestDataFunc) gs_plugins_dummy_install_func); g_test_add_data_func ("/gnome-software/plugins/dummy/error", plugin_loader, (GTestDataFunc) gs_plugins_dummy_error_func); g_test_add_data_func ("/gnome-software/plugins/dummy/installed", plugin_loader, (GTestDataFunc) gs_plugins_dummy_installed_func); g_test_add_data_func ("/gnome-software/plugins/dummy/refine", plugin_loader, (GTestDataFunc) gs_plugins_dummy_refine_func); g_test_add_data_func ("/gnome-software/plugins/dummy/updates", plugin_loader, (GTestDataFunc) gs_plugins_dummy_updates_func); g_test_add_data_func ("/gnome-software/plugins/dummy/distro-upgrades", plugin_loader, (GTestDataFunc) gs_plugins_dummy_distro_upgrades_func); g_test_add_data_func ("/gnome-software/plugins/dummy/metadata-quirks", plugin_loader, (GTestDataFunc) gs_plugins_dummy_metadata_quirks); g_test_add_data_func ("/gnome-software/plugins/dummy/limit-parallel-ops", plugin_loader, (GTestDataFunc) gs_plugins_dummy_limit_parallel_ops_func); g_test_add_data_func ("/gnome-software/plugins/dummy/app-size-calc", plugin_loader, (GTestDataFunc) gs_plugins_dummy_app_size_calc_func); retval = g_test_run (); /* Clean up. */ gs_utils_rmtree (tmp_root, NULL); return retval; }