diff options
Diffstat (limited to 'plugins/dummy/gs-self-test.c')
-rw-r--r-- | plugins/dummy/gs-self-test.c | 898 |
1 files changed, 898 insertions, 0 deletions
diff --git a/plugins/dummy/gs-self-test.c b/plugins/dummy/gs-self-test.c new file mode 100644 index 0000000..30360cc --- /dev/null +++ b/plugins/dummy/gs-self-test.c @@ -0,0 +1,898 @@ +/* -*- 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 <richard@hughsie.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include "config.h" + +#include <glib/gstdio.h> + +#include "gnome-software-private.h" + +#include "gs-test.h" + +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; + + /* install */ + app = gs_app_new ("chiron.desktop"); + gs_app_set_management_plugin (app, "dummy"); + gs_app_set_state (app, AS_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), ==, AS_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), ==, AS_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; + + /* drop all caches */ + gs_utils_rmtree (g_getenv ("GS_SELF_TEST_CACHEDIR"), NULL); + gs_plugin_loader_setup_again (plugin_loader); + + /* update, which should cause an error to be emitted */ + app = gs_app_new ("chiron.desktop"); + gs_app_set_management_plugin (app, "dummy"); + gs_app_set_state (app, AS_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; + + /* get the extra bits */ + app = gs_app_new ("chiron.desktop"); + gs_app_set_management_plugin (app, "dummy"); + plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_REFINE, + "app", app, + "refine-flags", GS_PLUGIN_REFINE_FLAGS_REQUIRE_DESCRIPTION | + GS_PLUGIN_REFINE_FLAGS_REQUIRE_LICENSE | + GS_PLUGIN_REFINE_FLAGS_REQUIRE_URL, + 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_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; + + /* get the extra bits */ + app = gs_app_new ("chiron.desktop"); + gs_app_set_management_plugin (app, "dummy"); + plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_REFINE, + "app", app, + "refine-flags", GS_PLUGIN_REFINE_FLAGS_REQUIRE_DESCRIPTION, + 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_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_newv (GS_PLUGIN_ACTION_REFINE, + "app", app, + "refine-flags", GS_PLUGIN_REFINE_FLAGS_REQUIRE_DESCRIPTION, + 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 (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_newv (GS_PLUGIN_ACTION_REFINE, + "app", app, + "refine-flags", GS_PLUGIN_REFINE_FLAGS_REQUIRE_DESCRIPTION, + 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 (!gs_app_has_quirk(app, GS_APP_QUIRK_NOT_LAUNCHABLE)); +} + +static void +gs_plugins_dummy_key_colors_func (GsPluginLoader *plugin_loader) +{ + GPtrArray *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 ("zeus.desktop"); + plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_REFINE, + "app", app, + "refine-flags", GS_PLUGIN_REFINE_FLAGS_REQUIRE_KEY_COLORS, + 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); + array = gs_app_get_key_colors (app); + g_assert_cmpint (array->len, >=, 3); + + /* check values are in range */ + for (i = 0; i < array->len; i++) { + GdkRGBA *kc = g_ptr_array_index (array, 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_APP_KIND_DESKTOP); + g_assert_cmpint (gs_app_get_state (app), ==, AS_APP_STATE_UPDATABLE_LIVE); + g_assert_cmpstr (gs_app_get_update_details (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), ==, "OS Updates"); + g_assert_cmpstr (gs_app_get_summary (app), ==, "Includes performance, stability and security improvements."); + g_assert_cmpint (gs_app_get_kind (app), ==, AS_APP_KIND_OS_UPDATE); + g_assert_cmpint (gs_app_get_state (app), ==, AS_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), ==, AS_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_newv (GS_PLUGIN_ACTION_GET_DISTRO_UPDATES, 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 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_APP_KIND_OS_UPGRADE); + g_assert_cmpint (gs_app_get_state (app), ==, AS_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), ==, AS_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), ==, AS_APP_STATE_UPDATABLE); +} + +static void +gs_plugins_dummy_installed_func (GsPluginLoader *plugin_loader) +{ + GsApp *app; + GsApp *addon; + GsAppList *addons; + g_autofree gchar *menu_path = NULL; + g_autoptr(GError) error = NULL; + g_autoptr(GsAppList) list = NULL; + g_autoptr(GsPluginJob) plugin_job = NULL; + + /* get installed packages */ + plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_GET_INSTALLED, + "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_MENU_PATH | + GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON | + GS_PLUGIN_REFINE_FLAGS_REQUIRE_CATEGORIES | + GS_PLUGIN_REFINE_FLAGS_REQUIRE_PROVENANCE, + 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 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_APP_KIND_DESKTOP); + g_assert_cmpint (gs_app_get_state (app), ==, AS_APP_STATE_INSTALLED); + g_assert_cmpstr (gs_app_get_name (app), ==, "Zeus"); + g_assert_cmpstr (gs_app_get_source_default (app), ==, "zeus"); + g_assert (gs_app_get_pixbuf (app) != NULL); + + /* 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, ==, "Audio & Video->Music Players"); + + /* check addon */ + addons = gs_app_get_addons (app); + 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_APP_KIND_ADDON); + g_assert_cmpint (gs_app_get_state (addon), ==, AS_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/"); + g_assert (gs_app_get_pixbuf (addon) == NULL); +} + +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; + + /* get search result based on addon keyword */ + plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_SEARCH, + "search", "zeus", + "refine-flags", GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON, + 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 is one entry, the parent 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), ==, "zeus.desktop"); + g_assert_cmpint (gs_app_get_kind (app), ==, AS_APP_KIND_DESKTOP); +} + +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(GsPluginJob) plugin_job = NULL; + + /* get search result based on addon keyword */ + app = gs_app_new ("zeus.desktop"); + plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_GET_ALTERNATES, + "app", app, + "refine-flags", GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON, + 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 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_APP_KIND_DESKTOP); + 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_APP_KIND_DESKTOP); +} + +static void +gs_plugins_dummy_hang_func (GsPluginLoader *plugin_loader) +{ + g_autoptr(GCancellable) cancellable = g_cancellable_new (); + g_autoptr(GError) error = NULL; + g_autoptr(GsAppList) list = NULL; + g_autoptr(GsPluginJob) plugin_job = NULL; + + /* drop all caches */ + gs_utils_rmtree (g_getenv ("GS_SELF_TEST_CACHEDIR"), NULL); + gs_plugin_loader_setup_again (plugin_loader); + + /* get search result based on addon keyword */ + plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_SEARCH, + "search", "hang", + "timeout", 1, /* seconds */ + NULL); + list = gs_plugin_loader_job_process (plugin_loader, plugin_job, cancellable, &error); + gs_test_flush_main_context (); + g_assert_error (error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_TIMED_OUT); + g_assert (list == NULL); +} + +static void +gs_plugins_dummy_search_invalid_func (GsPluginLoader *plugin_loader) +{ + g_autoptr(GError) error = NULL; + g_autoptr(GsAppList) list = NULL; + g_autoptr(GsPluginJob) plugin_job = NULL; + + /* get search result based on addon keyword */ + plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_SEARCH, + "search", "X", + NULL); + list = gs_plugin_loader_job_process (plugin_loader, plugin_job, NULL, &error); + gs_test_flush_main_context (); + g_assert_error (error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_NOT_SUPPORTED); + g_assert (list == NULL); +} + +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_APP_KIND_DESKTOP); +} + +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_newv (GS_PLUGIN_ACTION_GET_DISTRO_UPDATES, NULL); + 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_newv (GS_PLUGIN_ACTION_GET_DISTRO_UPDATES, NULL); + 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 *popular_override = "chiron.desktop,zeus.desktop"; + g_auto(GStrv) apps = NULL; + g_autoptr(GsPluginJob) plugin_job = NULL; + + /* use the plugin's add_popular function */ + plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_GET_POPULAR, + "refine-flags", GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON, + NULL); + 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); + + /* override the popular list (do not use the add_popular function) */ + g_setenv ("GNOME_SOFTWARE_POPULAR", popular_override, TRUE); + g_object_unref (plugin_job); + plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_GET_POPULAR, + "refine-flags", GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON, + NULL); + 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); + + apps = g_strsplit (popular_override, ",", 0); + g_assert_cmpint (gs_app_list_length (list2), ==, g_strv_length (apps)); + + for (guint i = 0; i < gs_app_list_length (list2); ++i) { + GsApp *app = gs_app_list_index (list2, i); + g_assert (g_strv_contains ((const gchar * const *) apps, 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; + 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_plugin_loader_setup_again (plugin_loader); + + /* get the updates list */ + plugin_job1 = gs_plugin_job_newv (GS_PLUGIN_ACTION_GET_DISTRO_UPDATES, NULL); + 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_APP_KIND_OS_UPGRADE); + g_assert_cmpint (gs_app_get_state (app1), ==, AS_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"); + gs_app_set_management_plugin (app2, "dummy"); + gs_app_set_state (app2, AS_APP_STATE_AVAILABLE); + + /* use "proxy" prefix so the update function succeeds... */ + app3 = gs_app_new ("proxy-zeus.desktop"); + gs_app_set_management_plugin (app3, "dummy"); + gs_app_set_state (app3, AS_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), ==, AS_APP_STATE_AVAILABLE); + g_assert_cmpint (gs_app_get_pending_action (app2), ==, GS_PLUGIN_ACTION_INSTALL); + g_assert_cmpint (gs_app_get_state (app3), ==, AS_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), ==, AS_APP_STATE_UPDATABLE); + g_assert_cmpint (gs_app_get_state (app2), ==, AS_APP_STATE_INSTALLED); + g_assert_cmpint (gs_app_get_state (app3), ==, AS_APP_STATE_INSTALLED); + + /* set the default max parallel ops */ + gs_plugin_loader_set_max_parallel_ops (plugin_loader, 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; + const gchar *allowlist[] = { + "appstream", + "dummy", + "generic-updates", + "hardcoded-blocklist", + "desktop-categories", + "desktop-menu-path", + "icons", + "key-colors", + "provenance", + "provenance-license", + 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. */ +#if GLIB_CHECK_VERSION(2, 60, 0) + g_content_type_set_mime_dirs (NULL); +#endif + + /* Similarly, add the system-wide icon theme path before it’s + * overwritten by %G_TEST_OPTION_ISOLATE_DIRS. */ + gs_test_expose_icon_theme_paths (); + + g_test_init (&argc, &argv, +#if GLIB_CHECK_VERSION(2, 60, 0) + G_TEST_OPTION_ISOLATE_DIRS, +#endif + NULL); + g_setenv ("G_MESSAGES_DEBUG", "all", TRUE); + g_setenv ("GS_XMLB_VERBOSE", "1", TRUE); + + /* set all the things required as a dummy test harness */ + g_setenv ("GS_SELF_TEST_LOCALE", "en_GB", TRUE); + 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); + g_setenv ("GNOME_SOFTWARE_POPULAR", "", 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 ("<?xml version=\"1.0\"?>\n" + "<components version=\"0.9\">\n" + " <component type=\"desktop\">\n" + " <id>chiron.desktop</id>\n" + " <name>Chiron</name>\n" + " <pkgname>chiron</pkgname>\n" + " </component>\n" + " <component type=\"desktop\">\n" + " <id>zeus.desktop</id>\n" + " <name>Zeus</name>\n" + " <summary>A teaching application</summary>\n" + " <pkgname>zeus</pkgname>\n" + " <icon type=\"stock\">drive-harddisk</icon>\n" + " <categories>\n" + " <category>AudioVideo</category>\n" + " <category>Player</category>\n" + " </categories>\n" + " <languages>\n" + " <lang percentage=\"100\">en_GB</lang>\n" + " </languages>\n" + " </component>\n" + " <component type=\"desktop\">\n" + " <id>mate-spell.desktop</id>\n" + " <name>Spell</name>\n" + " <summary>A spelling application for MATE</summary>\n" + " <pkgname>mate-spell</pkgname>\n" + " <icon type=\"stock\">drive-harddisk</icon>\n" + " <project_group>MATE</project_group>\n" + " </component>\n" + " <component type=\"addon\">\n" + " <id>zeus-spell.addon</id>\n" + " <extends>zeus.desktop</extends>\n" + " <name>Spell Check</name>\n" + " <summary>Check the spelling when teaching</summary>\n" + " <pkgname>zeus-spell</pkgname>\n" + " </component>\n" + " <component type=\"desktop\">\n" + " <id>Uninstall Zeus.desktop</id>\n" + " <name>Uninstall Zeus</name>\n" + " <summary>Uninstall the teaching application</summary>\n" + " <icon type=\"stock\">drive-harddisk</icon>\n" + " </component>\n" + " <component type=\"os-upgrade\">\n" + " <id>org.fedoraproject.release-rawhide.upgrade</id>\n" + " <name>Fedora Rawhide</name>\n" + " <summary>Release specific tagline</summary>\n" + " <pkgname>fedora-release</pkgname>\n" + " </component>\n" + " <info>\n" + " <scope>user</scope>\n" + " </info>\n" + "</components>\n"); + g_setenv ("GS_SELF_TEST_APPSTREAM_XML", xml, TRUE); + + /* only critical and error are fatal */ + g_log_set_fatal_mask (NULL, G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL); + + /* we can only load this once per process */ + plugin_loader = gs_plugin_loader_new (); + 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, + (gchar**) 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/hang", + plugin_loader, + (GTestDataFunc) gs_plugins_dummy_hang_func); + g_test_add_data_func ("/gnome-software/plugins/dummy/search{invalid}", + plugin_loader, + (GTestDataFunc) gs_plugins_dummy_search_invalid_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); + retval = g_test_run (); + + /* Clean up. */ + gs_utils_rmtree (tmp_root, NULL); + + return retval; +} |