Files
flatpak/tests/testlibrary.c
Umang Jain ceab716ab6 installation: Mark apps as updatable if their runtime is missing
Mark installed apps to be updatable if an installed in missing
its runtime for some reasons. In pre-FlatpakTransaction world,
an app migration from runtime X to runtime Y would have rendered
an app unusable because runtime Y would not be installed
automatically by clients like gnome-software.

The goal here is that clients like gnome-software can show
those installed apps as updatable again, if such a situation
arises. The FlatpakTransaction API can automatically resolve one of
its ops to install the new runtime, provided we can mark the app
as updatable again at the first place.
2019-11-22 16:08:32 +01:00

4105 lines
142 KiB
C

#include "config.h"
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <glib.h>
#include <ostree.h>
#include "libglnx/libglnx.h"
#include "flatpak.h"
static char *testdir;
static char *flatpak_runtimedir;
static char *flatpak_systemdir;
static char *flatpak_systemcachedir;
static char *flatpak_configdir;
static char *flatpak_installationsdir;
static char *gpg_homedir;
static char *gpg_args;
static char *repo_url;
static char *repo_collection_id;
static char *httpd_port;
int httpd_pid = -1;
static const char *gpg_id = "7B0961FD";
const char *repo_name = "test-repo";
typedef enum {
RUN_TEST_SUBPROCESS_DEFAULT = 0,
RUN_TEST_SUBPROCESS_IGNORE_FAILURE = (1 << 0),
RUN_TEST_SUBPROCESS_NO_CAPTURE = (1 << 1),
} RunTestSubprocessFlags;
static void run_test_subprocess (char **argv,
RunTestSubprocessFlags flags);
static void empty_installation (FlatpakInstallation *inst);
typedef struct
{
const char *id;
const char *display_name;
gint priority;
FlatpakStorageType storage_type;
} InstallationExtraData;
static void
test_library_version (void)
{
g_autofree char *version = NULL;
version = g_strdup_printf ("%d.%d.%d" G_STRINGIFY (PACKAGE_EXTRA_VERSION),
FLATPAK_MAJOR_VERSION,
FLATPAK_MINOR_VERSION,
FLATPAK_MICRO_VERSION);
g_assert_cmpstr (version, ==, PACKAGE_VERSION);
}
static void
test_library_types (void)
{
g_assert (g_type_is_a (FLATPAK_TYPE_REF, G_TYPE_OBJECT));
g_assert (g_type_is_a (FLATPAK_TYPE_INSTALLED_REF, FLATPAK_TYPE_REF));
g_assert (g_type_is_a (FLATPAK_TYPE_REMOTE_REF, FLATPAK_TYPE_REF));
g_assert (g_type_is_a (FLATPAK_TYPE_BUNDLE_REF, FLATPAK_TYPE_REF));
g_assert (g_type_is_a (FLATPAK_TYPE_RELATED_REF, FLATPAK_TYPE_REF));
g_assert (g_type_is_a (FLATPAK_TYPE_INSTALLATION, G_TYPE_OBJECT));
g_assert (g_type_is_a (FLATPAK_TYPE_INSTANCE, G_TYPE_OBJECT));
g_assert (g_type_is_a (FLATPAK_TYPE_REMOTE, G_TYPE_OBJECT));
g_assert (g_type_is_a (FLATPAK_TYPE_TRANSACTION, G_TYPE_OBJECT));
g_assert (g_type_is_a (FLATPAK_TYPE_TRANSACTION_OPERATION, G_TYPE_OBJECT));
g_assert (g_type_is_a (FLATPAK_TYPE_TRANSACTION_PROGRESS, G_TYPE_OBJECT));
g_assert (g_type_is_a (FLATPAK_TYPE_ERROR, G_TYPE_ENUM));
g_assert (g_type_is_a (FLATPAK_TYPE_PORTAL_ERROR, G_TYPE_ENUM));
g_assert (g_type_is_a (FLATPAK_TYPE_INSTALL_FLAGS, G_TYPE_FLAGS));
g_assert (g_type_is_a (FLATPAK_TYPE_UPDATE_FLAGS, G_TYPE_FLAGS));
g_assert (g_type_is_a (FLATPAK_TYPE_UNINSTALL_FLAGS, G_TYPE_FLAGS));
g_assert (g_type_is_a (FLATPAK_TYPE_STORAGE_TYPE, G_TYPE_ENUM));
g_assert (g_type_is_a (FLATPAK_TYPE_REF_KIND, G_TYPE_ENUM));
g_assert (g_type_is_a (FLATPAK_TYPE_REMOTE_TYPE, G_TYPE_ENUM));
g_assert (g_type_is_a (FLATPAK_TYPE_TRANSACTION_OPERATION_TYPE, G_TYPE_ENUM));
g_assert (g_type_is_a (FLATPAK_TYPE_TRANSACTION_ERROR_DETAILS, G_TYPE_FLAGS));
g_assert (g_type_is_a (FLATPAK_TYPE_TRANSACTION_RESULT, G_TYPE_FLAGS));
g_assert (g_type_is_a (FLATPAK_TYPE_TRANSACTION_REMOTE_REASON, G_TYPE_ENUM));
}
static void
test_user_installation (void)
{
g_autoptr(FlatpakInstallation) inst = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(GFile) dir = NULL;
g_autofree char *path = NULL;
g_autofree char *expected_path = NULL;
inst = flatpak_installation_new_user (NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (inst);
g_assert_true (flatpak_installation_get_is_user (inst));
dir = flatpak_installation_get_path (inst);
path = g_file_get_path (dir);
expected_path = g_build_filename (g_get_user_data_dir (), "flatpak", NULL);
g_assert_cmpstr (path, ==, expected_path);
}
static void
test_system_installation (void)
{
g_autoptr(FlatpakInstallation) inst = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(GFile) dir = NULL;
g_autofree char *path = NULL;
inst = flatpak_installation_new_system (NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (inst);
g_assert_false (flatpak_installation_get_is_user (inst));
dir = flatpak_installation_get_path (inst);
path = g_file_get_path (dir);
g_assert_cmpstr (path, ==, flatpak_systemdir);
}
static void
test_multiple_system_installations (void)
{
/* This is sorted according to the specific priority of each installation */
static InstallationExtraData expected_installations[] = {
{ "extra-installation-2", "Extra system installation 2", 25, FLATPAK_STORAGE_TYPE_SDCARD},
{ "extra-installation-1", "Extra system installation 1", 10, FLATPAK_STORAGE_TYPE_MMC},
{ "extra-installation-3", "System (extra-installation-3) installation", 0, FLATPAK_STORAGE_TYPE_DEFAULT},
{ "default", "Default system installation", 0, FLATPAK_STORAGE_TYPE_DEFAULT},
};
g_autoptr(GPtrArray) system_dirs = NULL;
g_autoptr(GError) error = NULL;
FlatpakInstallation *installation = NULL;
const char *current_id = NULL;
const char *current_display_name = NULL;
gint current_priority = 0;
FlatpakStorageType current_storage_type = FLATPAK_STORAGE_TYPE_DEFAULT;
int i;
system_dirs = flatpak_get_system_installations (NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (system_dirs);
g_assert_cmpint (system_dirs->len, ==, 4);
for (i = 0; i < system_dirs->len; i++)
{
g_autoptr(FlatpakInstallation) new_install = NULL;
g_autoptr(GFile) installation_path = NULL;
g_autofree char *path_str = NULL;
installation = (FlatpakInstallation *) g_ptr_array_index (system_dirs, i);
g_assert_false (flatpak_installation_get_is_user (installation));
installation_path = flatpak_installation_get_path (installation);
g_assert_nonnull (installation_path);
current_id = flatpak_installation_get_id (installation);
g_assert_cmpstr (current_id, ==, expected_installations[i].id);
path_str = g_file_get_path (installation_path);
if (g_strcmp0 (current_id, "default") == 0)
g_assert_cmpstr (path_str, ==, flatpak_systemdir);
else
g_assert_cmpstr (path_str, !=, flatpak_systemdir);
current_display_name = flatpak_installation_get_display_name (installation);
g_assert_cmpstr (current_display_name, ==, expected_installations[i].display_name);
current_priority = flatpak_installation_get_priority (installation);
g_assert_cmpint (current_priority, ==, expected_installations[i].priority);
current_storage_type = flatpak_installation_get_storage_type (installation);
g_assert_cmpint (current_storage_type, ==, expected_installations[i].storage_type);
/* Now test that flatpak_installation_new_system_with_id() works too */
new_install = flatpak_installation_new_system_with_id (current_id, NULL, &error);
g_assert_nonnull (new_install);
g_assert_cmpstr (current_id, ==, flatpak_installation_get_id (new_install));
g_assert_cmpstr (current_display_name, ==, flatpak_installation_get_display_name (new_install));
g_assert_cmpint (current_priority, ==, flatpak_installation_get_priority (new_install));
g_assert_cmpint (current_storage_type, ==, flatpak_installation_get_storage_type (new_install));
}
}
static void
test_installation_config (void)
{
g_autoptr(FlatpakInstallation) inst = NULL;
g_autofree char *path = NULL;
g_autoptr(GFile) file = NULL;
g_autoptr(GError) error = NULL;
g_autofree char *value;
gboolean res;
guint64 bytes;
path = g_build_filename (g_get_user_data_dir (), "flatpak", NULL);
file = g_file_new_for_path (path);
inst = flatpak_installation_new_for_path (file, TRUE, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (inst);
value = flatpak_installation_get_config (inst, "test", NULL, &error);
g_assert_null (value);
g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND);
g_clear_error (&error);
res = flatpak_installation_set_config_sync (inst, "test", "hello", NULL, &error);
g_assert_true (res);
g_assert_no_error (error);
value = flatpak_installation_get_config (inst, "test", NULL, &error);
g_assert_cmpstr (value, ==, "hello");
g_assert_no_error (error);
g_clear_pointer (&value, g_free);
g_clear_object (&inst);
inst = flatpak_installation_new_user (NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (inst);
value = flatpak_installation_get_config (inst, "test", NULL, &error);
g_assert_cmpstr (value, ==, "hello");
g_assert_no_error (error);
g_clear_pointer (&value, g_free);
res = flatpak_installation_get_min_free_space_bytes (inst, &bytes, &error);
g_assert_true (res);
g_assert_no_error (error);
}
static void
configure_languages (void)
{
char *argv[] = { "flatpak", "config", "--user", "--set", "languages", "de", NULL };
run_test_subprocess (argv, RUN_TEST_SUBPROCESS_DEFAULT);
}
static void
clean_languages (void)
{
char *argv[] = { "flatpak", "config", "--user", "--unset", "languages", NULL };
run_test_subprocess (argv, RUN_TEST_SUBPROCESS_DEFAULT);
}
static void
configure_extra_languages (void)
{
char *argv[] = { "flatpak", "config", "--user", "--set", "extra-languages", "de_DE", NULL };
run_test_subprocess (argv, RUN_TEST_SUBPROCESS_DEFAULT);
}
static void
clean_extra_languages (void)
{
char *argv[] = { "flatpak", "config", "--user", "--unset", "extra-languages", NULL };
run_test_subprocess (argv, RUN_TEST_SUBPROCESS_DEFAULT);
}
static void
test_languages_config (void)
{
g_autoptr(FlatpakInstallation) inst = NULL;
g_autofree char *path = NULL;
g_autoptr(GFile) file = NULL;
g_autoptr(GError) error = NULL;
g_auto(GStrv) value = NULL;
gboolean res;
clean_languages ();
path = g_build_filename (g_get_user_data_dir (), "flatpak", NULL);
file = g_file_new_for_path (path);
inst = flatpak_installation_new_for_path (file, TRUE, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (inst);
value = flatpak_installation_get_default_languages (inst, &error);
g_assert_no_error (error);
g_assert_cmpstr (value[0], ==, "en");
g_assert_null (value[1]);
res = flatpak_installation_set_config_sync (inst, "extra-languages", "pt_BR;uz_UZ.utf8@cyrillic;es;zh_HK.big5hkscs;uz_UZ@cyrillic", NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
value = flatpak_installation_get_default_languages (inst, &error);
g_assert_no_error (error);
g_assert_cmpstr (value[0], ==, "en");
g_assert_cmpstr (value[1], ==, "es");
g_assert_cmpstr (value[2], ==, "pt");
g_assert_cmpstr (value[3], ==, "uz");
g_assert_cmpstr (value[4], ==, "zh");
g_assert_null (value[5]);
g_clear_pointer (&value, g_strfreev);
value = flatpak_installation_get_default_locales (inst, &error);
g_assert_no_error (error);
g_assert_cmpstr (value[0], ==, "en");
g_assert_cmpstr (value[1], ==, "es");
g_assert_cmpstr (value[2], ==, "pt_BR");
g_assert_cmpstr (value[3], ==, "uz_UZ.utf8@cyrillic");
g_assert_cmpstr (value[4], ==, "uz_UZ@cyrillic");
g_assert_cmpstr (value[5], ==, "zh_HK.big5hkscs");
g_assert_null (value[6]);
g_clear_pointer (&value, g_strfreev);
res = flatpak_installation_set_config_sync (inst, "languages", "ar;es", NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
value = flatpak_installation_get_default_languages (inst, &error);
g_assert_no_error (error);
g_assert_cmpstr (value[0], ==, "ar");
g_assert_cmpstr (value[1], ==, "es");
g_assert_null (value[2]);
g_clear_pointer (&value, g_strfreev);
clean_extra_languages ();
configure_languages ();
}
static void
test_arches (void)
{
const char *default_arch;
const char *const *supported_arches;
default_arch = flatpak_get_default_arch ();
supported_arches = flatpak_get_supported_arches ();
g_assert_nonnull (default_arch);
g_assert_cmpstr (default_arch, !=, "");
g_assert_nonnull (supported_arches);
g_assert (g_strv_contains (supported_arches, default_arch));
}
static void
test_ref (void)
{
g_autoptr(FlatpakRef) ref = NULL;
g_autoptr(GError) error = NULL;
g_autofree char *formatted = NULL;
const char *valid;
FlatpakRefKind kind;
g_autofree char *name = NULL;
g_autofree char *arch = NULL;
g_autofree char *branch = NULL;
g_autofree char *commit = NULL;
g_autofree char *collection_id = NULL;
ref = flatpak_ref_parse ("", &error);
g_assert_null (ref);
g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_INVALID_REF);
g_clear_error (&error);
ref = flatpak_ref_parse ("ref/or not", &error);
g_assert_null (ref);
g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_INVALID_REF);
g_clear_error (&error);
ref = flatpak_ref_parse ("ref/one/2/3", &error);
g_assert_null (ref);
g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_INVALID_REF);
g_clear_error (&error);
ref = flatpak_ref_parse ("app/a/b/c", &error);
g_assert_null (ref);
g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_INVALID_REF);
g_clear_error (&error);
ref = flatpak_ref_parse ("app/org.flatpak.Hello/b/.", &error);
g_assert_null (ref);
g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_INVALID_REF);
g_clear_error (&error);
ref = flatpak_ref_parse ("foo/org.flatpak.Hello/b/.", &error);
g_assert_null (ref);
g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_INVALID_REF);
g_clear_error (&error);
ref = flatpak_ref_parse ("app//m68k/master", &error);
g_assert_null (ref);
g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_INVALID_REF);
g_clear_error (&error);
ref = flatpak_ref_parse ("app/org.test.Hello/m68k/", &error);
g_assert_null (ref);
g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_INVALID_REF);
g_clear_error (&error);
ref = flatpak_ref_parse ("app/org.test.Hello/m68k/a[b]c", &error);
g_assert_null (ref);
g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_INVALID_REF);
g_clear_error (&error);
ref = flatpak_ref_parse ("app/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"/m68k/master", &error);
g_assert_null (ref);
g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_INVALID_REF);
g_clear_error (&error);
ref = flatpak_ref_parse ("app/.abc/m68k/master", &error);
g_assert_null (ref);
g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_INVALID_REF);
g_clear_error (&error);
ref = flatpak_ref_parse ("app/0abc/m68k/master", &error);
g_assert_null (ref);
g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_INVALID_REF);
g_clear_error (&error);
valid = "app/org.flatpak.Hello/m68k/master";
ref = flatpak_ref_parse (valid, &error);
g_assert_no_error (error);
g_assert (FLATPAK_IS_REF (ref));
g_assert_cmpint (flatpak_ref_get_kind (ref), ==, FLATPAK_REF_KIND_APP);
g_assert_cmpstr (flatpak_ref_get_name (ref), ==, "org.flatpak.Hello");
g_assert_cmpstr (flatpak_ref_get_arch (ref), ==, "m68k");
g_assert_cmpstr (flatpak_ref_get_branch (ref), ==, "master");
g_assert_null (flatpak_ref_get_collection_id (ref));
formatted = flatpak_ref_format_ref (ref);
g_assert_cmpstr (formatted, ==, valid);
g_clear_object (&ref);
valid = "runtime/org.gnome.Platform/m68k/stable";
ref = flatpak_ref_parse (valid, &error);
g_assert_no_error (error);
g_assert (FLATPAK_IS_REF (ref));
g_object_get (ref,
"kind", &kind,
"name", &name,
"arch", &arch,
"branch", &branch,
"commit", &commit,
"collection-id", &collection_id,
NULL);
g_assert_cmpint (kind, ==, FLATPAK_REF_KIND_RUNTIME);
g_assert_cmpstr (name, ==, "org.gnome.Platform");
g_assert_cmpstr (arch, ==, "m68k");
g_assert_cmpstr (branch, ==, "stable");
g_assert_null (commit);
g_assert_null (collection_id);
formatted = flatpak_ref_format_ref (ref);
g_assert_cmpstr (formatted, ==, valid);
g_clear_object (&ref);
ref = g_object_new (FLATPAK_TYPE_REF,
"kind", FLATPAK_REF_KIND_RUNTIME,
"name", "org.gnome.Platform",
"arch", "m68k",
"branch", "stable",
"commit", "0123456789",
"collection-id", "org.flathub.Stable",
NULL);
g_assert_cmpstr (flatpak_ref_get_commit (ref), ==, "0123456789");
g_assert_cmpstr (flatpak_ref_get_collection_id (ref), ==, "org.flathub.Stable");
g_clear_object (&ref);
}
static void
test_list_remotes (void)
{
g_autoptr(FlatpakInstallation) inst = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(GPtrArray) remotes = NULL;
g_autoptr(GPtrArray) remotes2 = NULL;
FlatpakRemote *remote;
const FlatpakRemoteType types[] = { FLATPAK_REMOTE_TYPE_STATIC };
const FlatpakRemoteType types2[] = { FLATPAK_REMOTE_TYPE_LAN };
gboolean res;
inst = flatpak_installation_new_user (NULL, &error);
g_assert_no_error (error);
res = flatpak_installation_update_remote_sync (inst, repo_name, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
res = flatpak_installation_update_appstream_sync (inst, repo_name, NULL, NULL, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
remotes = flatpak_installation_list_remotes (inst, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (remotes);
g_assert (remotes->len == 1);
remote = g_ptr_array_index (remotes, 0);
g_assert (FLATPAK_IS_REMOTE (remote));
remotes2 = flatpak_installation_list_remotes_by_type (inst, types,
G_N_ELEMENTS (types),
NULL, &error);
g_assert_no_error (error);
g_assert_cmpuint (remotes2->len, ==, remotes->len);
for (guint i = 0; i < remotes->len; ++i)
{
FlatpakRemote *remote1 = g_ptr_array_index (remotes, i);
FlatpakRemote *remote2 = g_ptr_array_index (remotes2, i);
g_assert_cmpstr (flatpak_remote_get_name (remote1), ==,
flatpak_remote_get_name (remote2));
g_assert_cmpstr (flatpak_remote_get_url (remote1), ==,
flatpak_remote_get_url (remote2));
}
g_ptr_array_unref (remotes2);
remotes2 = flatpak_installation_list_remotes_by_type (inst,
types2,
G_N_ELEMENTS (types2),
NULL, &error);
g_assert_no_error (error);
g_assert_cmpuint (remotes2->len, ==, 0);
}
static void
test_remote_by_name (void)
{
g_autoptr(FlatpakInstallation) inst = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(FlatpakRemote) remote = NULL;
g_autofree char *name = NULL;
FlatpakRemoteType type;
g_autoptr(GFile) file = NULL;
inst = flatpak_installation_new_user (NULL, &error);
g_assert_no_error (error);
remote = flatpak_installation_get_remote_by_name (inst, repo_name, NULL, &error);
g_assert_no_error (error);
g_assert (FLATPAK_IS_REMOTE (remote));
g_assert_cmpstr (flatpak_remote_get_name (remote), ==, repo_name);
g_assert_cmpstr (flatpak_remote_get_url (remote), ==, repo_url);
g_assert_cmpstr (flatpak_remote_get_title (remote), ==, NULL);
g_assert_cmpint (flatpak_remote_get_remote_type (remote), ==, FLATPAK_REMOTE_TYPE_STATIC);
g_assert_false (flatpak_remote_get_noenumerate (remote));
g_assert_false (flatpak_remote_get_disabled (remote));
g_assert_true (flatpak_remote_get_gpg_verify (remote));
g_assert_cmpint (flatpak_remote_get_prio (remote), ==, 1);
g_assert_cmpstr (flatpak_remote_get_collection_id (remote), ==, repo_collection_id);
g_object_get (remote,
"name", &name,
"type", &type,
NULL);
g_assert_cmpstr (name, ==, repo_name);
g_assert_cmpint (type, ==, FLATPAK_REMOTE_TYPE_STATIC);
file = flatpak_remote_get_appstream_dir (remote, NULL);
g_assert_nonnull (file);
g_clear_object (&file);
file = flatpak_remote_get_appstream_timestamp (remote, NULL);
g_assert_nonnull (file);
}
static void
test_remote (void)
{
g_autoptr(FlatpakInstallation) inst = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(FlatpakRemote) remote = NULL;
g_autoptr(GFile) inst_file = NULL;
g_autoptr(GFile) repo_file = NULL;
g_autoptr(OstreeRepo) repo = NULL;
gboolean gpg_verify_summary;
gboolean res;
inst = flatpak_installation_new_user (NULL, &error);
g_assert_no_error (error);
remote = flatpak_installation_get_remote_by_name (inst, repo_name, NULL, &error);
g_assert_no_error (error);
g_assert_cmpstr (flatpak_remote_get_collection_id (remote), ==, repo_collection_id);
/* Flatpak doesn't provide access to gpg-verify-summary, so use ostree */
res = flatpak_installation_modify_remote (inst, remote, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
inst_file = flatpak_installation_get_path (inst);
repo_file = g_file_get_child (inst_file, "repo");
repo = ostree_repo_new (repo_file);
res = ostree_repo_open (repo, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
res = ostree_repo_get_remote_boolean_option (repo, repo_name, "gpg-verify-summary", TRUE, &gpg_verify_summary, &error);
g_assert_no_error (error);
g_assert_true (res);
g_assert_false (gpg_verify_summary);
/* Temporarily unset the collection ID */
flatpak_remote_set_collection_id (remote, NULL);
g_assert_cmpstr (flatpak_remote_get_collection_id (remote), ==, NULL);
res = flatpak_installation_modify_remote (inst, remote, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
res = ostree_repo_reload_config (repo, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
res = ostree_repo_get_remote_boolean_option (repo, repo_name, "gpg-verify-summary", FALSE, &gpg_verify_summary, &error);
g_assert_no_error (error);
g_assert_true (res);
g_assert_true (gpg_verify_summary);
flatpak_remote_set_collection_id (remote, repo_collection_id);
g_assert_cmpstr (flatpak_remote_get_collection_id (remote), ==, repo_collection_id);
g_assert_cmpstr (flatpak_remote_get_title (remote), ==, NULL);
flatpak_remote_set_title (remote, "Test Repo");
g_assert_cmpstr (flatpak_remote_get_title (remote), ==, "Test Repo");
g_assert_cmpint (flatpak_remote_get_prio (remote), ==, 1);
flatpak_remote_set_prio (remote, 15);
g_assert_cmpint (flatpak_remote_get_prio (remote), ==, 15);
g_assert_false (flatpak_remote_get_noenumerate (remote));
flatpak_remote_set_noenumerate (remote, TRUE);
g_assert_true (flatpak_remote_get_noenumerate (remote));
g_assert_false (flatpak_remote_get_nodeps (remote));
flatpak_remote_set_nodeps (remote, TRUE);
g_assert_true (flatpak_remote_get_nodeps (remote));
g_assert_false (flatpak_remote_get_disabled (remote));
flatpak_remote_set_disabled (remote, TRUE);
g_assert_true (flatpak_remote_get_disabled (remote));
g_assert_null (flatpak_remote_get_default_branch (remote));
flatpak_remote_set_default_branch (remote, "master");
g_assert_cmpstr (flatpak_remote_get_default_branch (remote), ==, "master");
/* It should be an error to disable GPG while a collection ID is set. */
g_assert_true (flatpak_remote_get_gpg_verify (remote));
flatpak_remote_set_gpg_verify (remote, FALSE);
g_assert_false (flatpak_remote_get_gpg_verify (remote));
res = flatpak_installation_modify_remote (inst, remote, NULL, &error);
g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_INVALID_DATA);
g_clear_error (&error);
g_assert_false (res);
/* Unset the collection ID and try again. */
flatpak_remote_set_collection_id (remote, NULL);
g_assert_cmpstr (flatpak_remote_get_collection_id (remote), ==, NULL);
g_assert_false (flatpak_remote_get_gpg_verify (remote));
res = flatpak_installation_modify_remote (inst, remote, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
g_clear_object (&remote);
remote = flatpak_installation_get_remote_by_name (inst, repo_name, NULL, &error);
g_assert_no_error (error);
g_assert_cmpstr (flatpak_remote_get_title (remote), ==, "Test Repo");
g_assert_cmpint (flatpak_remote_get_prio (remote), ==, 15);
g_assert_true (flatpak_remote_get_noenumerate (remote));
g_assert_true (flatpak_remote_get_nodeps (remote));
g_assert_false (flatpak_remote_get_gpg_verify (remote));
g_assert_cmpstr (flatpak_remote_get_default_branch (remote), ==, "master");
/* back to defaults */
flatpak_remote_set_noenumerate (remote, FALSE);
flatpak_remote_set_nodeps (remote, FALSE);
flatpak_remote_set_disabled (remote, FALSE);
flatpak_remote_set_gpg_verify (remote, TRUE);
flatpak_remote_set_collection_id (remote, repo_collection_id);
res = flatpak_installation_modify_remote (inst, remote, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
}
static void
test_remote_new (void)
{
g_autoptr(FlatpakInstallation) inst = NULL;
g_autoptr(FlatpakRemote) remote = NULL;
g_autoptr(GError) error = NULL;
gboolean res;
inst = flatpak_installation_new_user (NULL, &error);
g_assert_no_error (error);
remote = flatpak_installation_get_remote_by_name (inst, "my-first-remote", NULL, &error);
g_assert_null (remote);
g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_REMOTE_NOT_FOUND);
g_clear_error (&error);
remote = flatpak_remote_new ("my-first-remote");
g_assert_null (flatpak_remote_get_appstream_dir (remote, NULL));
g_assert_null (flatpak_remote_get_appstream_timestamp (remote, NULL));
g_assert_null (flatpak_remote_get_url (remote));
g_assert_null (flatpak_remote_get_collection_id (remote));
g_assert_null (flatpak_remote_get_title (remote));
g_assert_null (flatpak_remote_get_default_branch (remote));
g_assert_false (flatpak_remote_get_noenumerate (remote));
g_assert_false (flatpak_remote_get_nodeps (remote));
g_assert_false (flatpak_remote_get_disabled (remote));
g_assert_cmpint (flatpak_remote_get_prio (remote), ==, 1);
g_assert_false (flatpak_remote_get_gpg_verify (remote));
res = flatpak_installation_add_remote (inst, remote, FALSE, NULL, &error);
g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_INVALID_DATA);
g_assert_false (res);
g_clear_error (&error);
flatpak_remote_set_url (remote, "http://127.0.0.1/nowhere");
res = flatpak_installation_add_remote (inst, remote, FALSE, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
g_clear_object (&remote);
remote = flatpak_installation_get_remote_by_name (inst, "my-first-remote", NULL, &error);
g_assert_no_error (error);
g_assert_cmpstr (flatpak_remote_get_url (remote), ==, "http://127.0.0.1/nowhere");
g_clear_object (&remote);
remote = flatpak_remote_new ("my-first-remote");
flatpak_remote_set_url (remote, "http://127.0.0.1/elsewhere");
res = flatpak_installation_add_remote (inst, remote, FALSE, NULL, &error);
g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_ALREADY_INSTALLED);
g_clear_error (&error);
g_assert_false (res);
/* add if needed */
res = flatpak_installation_add_remote (inst, remote, TRUE, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
g_clear_object (&remote);
remote = flatpak_installation_get_remote_by_name (inst, "my-first-remote", NULL, &error);
g_assert_no_error (error);
/* Should be the old value */
g_assert_cmpstr (flatpak_remote_get_url (remote), ==, "http://127.0.0.1/nowhere");
g_clear_object (&remote);
res = flatpak_installation_remove_remote (inst, "my-first-remote", NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
remote = flatpak_installation_get_remote_by_name (inst, "my-first-remote", NULL, &error);
g_assert_null (remote);
g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_REMOTE_NOT_FOUND);
g_clear_error (&error);
}
static void
test_remote_new_from_file (void)
{
g_autoptr(FlatpakInstallation) inst = NULL;
g_autoptr(FlatpakRemote) remote = NULL;
g_autoptr(GError) error = NULL;
gboolean res;
const char *_data =
"[Flatpak Repo]\n"
"Url=http://127.0.0.1/repo\n"
"Title=The Title\n"
"Comment=The Comment\n"
"Description=The Description\n"
"Homepage=https://the.homepage/\n"
"Icon=https://the.icon/\n"
"DefaultBranch=default-branch\n"
"NoDeps=true\n";
g_autoptr(GBytes) data = g_bytes_new_static (_data, strlen (_data));
inst = flatpak_installation_new_user (NULL, &error);
g_assert_no_error (error);
remote = flatpak_installation_get_remote_by_name (inst, "file-remote", NULL, &error);
g_assert_null (remote);
g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_REMOTE_NOT_FOUND);
g_clear_error (&error);
remote = flatpak_remote_new_from_file ("file-remote", data, &error);
g_assert_nonnull (remote);
g_assert_no_error (error);
res = flatpak_installation_add_remote (inst, remote, FALSE, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
g_clear_object (&remote);
remote = flatpak_installation_get_remote_by_name (inst, "file-remote", NULL, &error);
g_assert_no_error (error);
g_assert_cmpstr (flatpak_remote_get_url (remote), ==, "http://127.0.0.1/repo");
g_assert_cmpstr (flatpak_remote_get_title (remote), ==, "The Title");
g_assert_cmpstr (flatpak_remote_get_comment (remote), ==, "The Comment");
g_assert_cmpstr (flatpak_remote_get_description (remote), ==, "The Description");
g_assert_cmpstr (flatpak_remote_get_homepage (remote), ==, "https://the.homepage/");
g_assert_cmpstr (flatpak_remote_get_icon (remote), ==, "https://the.icon/");
g_assert_cmpstr (flatpak_remote_get_default_branch (remote), ==, "default-branch");
g_assert_cmpint (flatpak_remote_get_nodeps (remote), ==, TRUE);
g_clear_object (&remote);
remote = flatpak_installation_get_remote_by_name (inst, "file-remote", NULL, &error);
g_assert_no_error (error);
g_assert_cmpstr (flatpak_remote_get_filter (remote), ==, NULL);
flatpak_remote_set_url (remote, "http://127.0.0.1/other");
flatpak_remote_set_filter (remote, "/some/path/to/filter");
res = flatpak_installation_modify_remote (inst, remote, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
g_clear_object (&remote);
remote = flatpak_installation_get_remote_by_name (inst, "file-remote", NULL, &error);
g_assert_no_error (error);
g_assert_cmpstr (flatpak_remote_get_url (remote), ==, "http://127.0.0.1/other");
g_assert_cmpstr (flatpak_remote_get_filter (remote), ==, "/some/path/to/filter");
g_clear_object (&remote);
remote = flatpak_remote_new_from_file ("file-remote", data, &error);
g_assert_nonnull (remote);
g_assert_no_error (error);
/* regular add fails */
res = flatpak_installation_add_remote (inst, remote, FALSE, NULL, &error);
g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_ALREADY_INSTALLED);
g_clear_error (&error);
g_assert_false (res);
/* add if needed succeeds and resets filter */
res = flatpak_installation_add_remote (inst, remote, TRUE, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
g_clear_object (&remote);
remote = flatpak_installation_get_remote_by_name (inst, "file-remote", NULL, &error);
g_assert_no_error (error);
g_assert_cmpstr (flatpak_remote_get_url (remote), ==, "http://127.0.0.1/other");
g_assert_cmpstr (flatpak_remote_get_filter (remote), ==, NULL);
g_clear_object (&remote);
}
static void
test_list_refs (void)
{
g_autoptr(FlatpakInstallation) inst = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(GPtrArray) refs = NULL;
inst = flatpak_installation_new_user (NULL, &error);
g_assert_no_error (error);
refs = flatpak_installation_list_installed_refs (inst, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (refs);
g_assert_cmpint (refs->len, ==, 0);
}
static void
create_multi_collection_id_repo (const char *repo_dir)
{
g_autofree char *arg0 = NULL;
/* Create a repository in which each app has a different collection-id */
arg0 = g_test_build_filename (G_TEST_DIST, "make-multi-collection-id-repo.sh", NULL);
const char *argv[] = { arg0, repo_dir, NULL };
run_test_subprocess ((char **) argv, RUN_TEST_SUBPROCESS_DEFAULT);
}
static void
test_list_refs_in_remotes (void)
{
const char *repo_name = "multi-refs-repo";
g_autofree char *repo_url = NULL;
g_autoptr(GPtrArray) refs1 = NULL;
g_autoptr(GPtrArray) refs2 = NULL;
g_autoptr(FlatpakInstallation) inst = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(FlatpakRemote) remote = NULL;
g_autofree char *repo_dir = g_build_filename (testdir, repo_name, NULL);
g_autofree char *repo_uri = NULL;
g_autoptr(GHashTable) collection_ids = g_hash_table_new_full (g_str_hash,
g_str_equal,
NULL, NULL);
g_autoptr(GHashTable) ref_specs = g_hash_table_new_full (g_str_hash,
g_str_equal,
g_free,
NULL);
create_multi_collection_id_repo (repo_dir);
repo_url = g_strdup_printf ("file://%s", repo_dir);
const char *argv[] = { "flatpak", "remote-add", "--user", "--no-gpg-verify",
repo_name, repo_url, NULL };
/* Add the repo we created above, which holds one collection ID per ref */
run_test_subprocess ((char **) argv, RUN_TEST_SUBPROCESS_DEFAULT);
inst = flatpak_installation_new_user (NULL, &error);
g_assert_no_error (error);
/* Ensure the remote can be successfully found */
remote = flatpak_installation_get_remote_by_name (inst, repo_name, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (remote);
/* List the refs in the remote we've just added */
refs1 = flatpak_installation_list_remote_refs_sync (inst, repo_name, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (refs1);
g_assert (refs1->len > 1);
/* Ensure that the number of different collection IDs is the same as the
* number of apps */
for (guint i = 0; i < refs1->len; ++i)
{
FlatpakRef *ref = g_ptr_array_index (refs1, i);
g_hash_table_add (collection_ids, (gchar *) flatpak_ref_get_collection_id (ref));
g_hash_table_add (ref_specs, flatpak_ref_format_ref (ref));
}
/* we have a locale extension for each app, thus the 2 */
g_assert_cmpuint (2 * g_hash_table_size (collection_ids), ==, refs1->len);
/* Ensure that listing the refs by using a remote's URI will get us the
* same results as using the name */
repo_uri = flatpak_remote_get_url (remote);
refs2 = flatpak_installation_list_remote_refs_sync (inst, repo_uri, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (refs2);
g_assert_cmpuint (refs2->len, ==, refs1->len);
for (guint i = 0; i < refs2->len; ++i)
{
FlatpakRef *ref = g_ptr_array_index (refs2, i);
g_autofree char *ref_spec = flatpak_ref_format_ref (ref);
g_assert_nonnull (g_hash_table_lookup (ref_specs, ref_spec));
}
}
static void
test_list_remote_refs (void)
{
g_autoptr(FlatpakInstallation) inst = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(GPtrArray) refs = NULL;
int i;
inst = flatpak_installation_new_user (NULL, &error);
g_assert_no_error (error);
refs = flatpak_installation_list_remote_refs_sync (inst, repo_name, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (refs);
g_assert_cmpint (refs->len, >, 1);
for (i = 0; i < refs->len; i++)
{
FlatpakRemoteRef *remote_ref = g_ptr_array_index (refs, i);
FlatpakRef *ref = FLATPAK_REF (remote_ref);
GBytes *metadata;
g_autoptr(GBytes) metadata2 = NULL;
g_autofree char *name = NULL;
guint64 installed_size;
guint64 download_size;
g_autofree char *eol = NULL;
g_autofree char *eol_rebase = NULL;
g_assert (ref != NULL);
if (strcmp ("org.test.Hello", flatpak_ref_get_name (ref)) == 0)
{
g_assert_cmpint (flatpak_ref_get_kind (ref), ==, FLATPAK_REF_KIND_APP);
}
else if (strcmp ("org.test.Hello.Locale", flatpak_ref_get_name (ref)) == 0)
{
g_assert_cmpint (flatpak_ref_get_kind (ref), ==, FLATPAK_REF_KIND_RUNTIME);
}
else
{
g_assert_cmpstr (flatpak_ref_get_name (ref), ==, "org.test.Platform");
g_assert_cmpint (flatpak_ref_get_kind (ref), ==, FLATPAK_REF_KIND_RUNTIME);
}
g_assert_cmpstr (flatpak_ref_get_branch (ref), ==, "master");
g_assert_cmpstr (flatpak_ref_get_commit (ref), !=, NULL);
g_assert_cmpstr (flatpak_ref_get_arch (ref), ==, flatpak_get_default_arch ());
g_assert_cmpstr (flatpak_remote_ref_get_remote_name (remote_ref), ==, repo_name);
g_assert_cmpstr (flatpak_remote_ref_get_eol (remote_ref), ==, NULL);
g_assert_cmpstr (flatpak_remote_ref_get_eol_rebase (remote_ref), ==, NULL);
g_assert_cmpuint (flatpak_remote_ref_get_installed_size (remote_ref), >, 0);
g_assert_cmpuint (flatpak_remote_ref_get_download_size (remote_ref), >, 0);
metadata = flatpak_remote_ref_get_metadata (remote_ref);
g_assert (metadata != NULL);
if (strcmp ("org.test.Hello", flatpak_ref_get_name (ref)) == 0)
g_assert (g_str_has_prefix ((char *) g_bytes_get_data (metadata, NULL), "[Application]"));
else
g_assert (g_str_has_prefix ((char *) g_bytes_get_data (metadata, NULL), "[Runtime]"));
g_object_get (ref,
"remote-name", &name,
"installed-size", &installed_size,
"download-size", &download_size,
"metadata", &metadata2,
"end-of-life", &eol,
"end-of-life-rebase", &eol_rebase,
NULL);
g_assert_cmpstr (name, ==, repo_name);
g_assert_cmpuint (installed_size, >, 0);
g_assert_cmpuint (download_size, >, 0);
g_assert (metadata2 == metadata);
g_assert_null (eol);
g_assert_null (eol_rebase);
}
}
static void
test_update_installed_ref_if_missing_runtime (void)
{
g_autoptr(FlatpakInstallation) inst = NULL;
g_autoptr(FlatpakTransaction) transaction = NULL;
g_autoptr(GPtrArray) updatable_refs = NULL;
g_autoptr(GError) error = NULL;
FlatpakInstalledRef *iref = NULL;
gboolean res;
g_autofree char *app = NULL;
app = g_strdup_printf ("app/org.test.Hello/%s/master",
flatpak_get_default_arch ());
inst = flatpak_installation_new_user (NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (inst);
empty_installation (inst);
/* Install the app */
iref = flatpak_installation_install (inst,
repo_name,
FLATPAK_REF_KIND_APP,
"org.test.Hello",
flatpak_get_default_arch (),
"master",
NULL, NULL, NULL, &error);
g_assert_no_error (error);
g_assert (FLATPAK_IS_INSTALLED_REF (iref));
iref = NULL;
/* Install the Locale extension */
iref = flatpak_installation_install (inst,
repo_name,
FLATPAK_REF_KIND_RUNTIME,
"org.test.Hello.Locale",
flatpak_get_default_arch (),
"master",
NULL, NULL, NULL, &error);
g_assert_no_error (error);
g_assert (FLATPAK_IS_INSTALLED_REF (iref));
iref = NULL;
updatable_refs = flatpak_installation_list_installed_refs_for_update (inst, NULL, &error);
g_assert_cmpint (updatable_refs->len, ==, 1);
iref = g_ptr_array_index (updatable_refs, 0);
g_assert_cmpstr (flatpak_ref_get_name (FLATPAK_REF (iref)), ==, "org.test.Hello");
iref = NULL;
/* Prepare an update transaction to update org.test.Hello. The missing org.test.Platform
runtime should automatically be installed with it. */
transaction = flatpak_transaction_new_for_installation (inst, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (transaction);
res = flatpak_transaction_add_update (transaction, app, NULL, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
res = flatpak_transaction_run (transaction, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
iref = flatpak_installation_get_installed_ref (inst, FLATPAK_REF_KIND_RUNTIME, "org.test.Platform", NULL, NULL, NULL, &error);
g_assert_nonnull (iref);
g_assert_no_error (error);
}
static void
test_update_related_refs (void)
{
g_autoptr(FlatpakInstallation) inst = NULL;
g_autoptr(FlatpakTransaction) transaction = NULL;
g_autoptr(GPtrArray) updatable_refs = NULL;
g_autoptr(GPtrArray) related_refs = NULL;
g_autoptr(GError) error = NULL;
FlatpakInstalledRef *iref = NULL;
g_autoptr(FlatpakInstalledRef) runtime_ref = NULL;
gboolean res;
g_autofree char *app = NULL;
app = g_strdup_printf ("app/org.test.Hello/%s/master",
flatpak_get_default_arch ());
inst = flatpak_installation_new_user (NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (inst);
empty_installation (inst);
/* Install a runtime */
runtime_ref = flatpak_installation_install (inst,
repo_name,
FLATPAK_REF_KIND_RUNTIME,
"org.test.Platform",
NULL, "master", NULL, NULL, NULL,
&error);
g_assert_no_error (error);
g_assert (FLATPAK_IS_INSTALLED_REF (runtime_ref));
iref = flatpak_installation_install (inst,
repo_name,
FLATPAK_REF_KIND_APP,
"org.test.Hello",
NULL, "master", NULL, NULL, NULL,
&error);
g_assert_no_error (error);
g_assert (FLATPAK_IS_INSTALLED_REF (iref));
iref = NULL;
/* We expect no installed related refs (i.e. org.test.Hello.Locale) at this point */
related_refs = flatpak_installation_list_installed_related_refs_sync (inst, repo_name, app, NULL, &error);
g_assert_cmpint (related_refs->len, ==, 0);
updatable_refs = flatpak_installation_list_installed_refs_for_update (inst, NULL, &error);
g_assert_cmpint (updatable_refs->len, ==, 1);
iref = g_ptr_array_index (updatable_refs, 0);
g_assert_cmpstr (flatpak_ref_get_name (FLATPAK_REF (iref)), ==, "org.test.Hello");
/* Prepare an update transaction to update org.test.Hello. The missing related .Locale
extension should automatically be installed with it. */
transaction = flatpak_transaction_new_for_installation (inst, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (transaction);
res = flatpak_transaction_add_update (transaction, app, NULL, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
res = flatpak_transaction_run (transaction, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
iref = flatpak_installation_get_installed_ref (inst, FLATPAK_REF_KIND_RUNTIME, "org.test.Hello.Locale", NULL, NULL, NULL, &error);
g_assert_nonnull (iref);
g_assert_no_error (error);
}
static void
test_list_remote_related_refs (void)
{
g_autoptr(FlatpakInstallation) inst = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(GPtrArray) refs = NULL;
FlatpakRelatedRef *ref;
g_auto(GStrv) subpaths = NULL;
gboolean should_download;
gboolean should_delete;
gboolean should_autoprune;
g_autofree char *app = NULL;
app = g_strdup_printf ("app/org.test.Hello/%s/master",
flatpak_get_default_arch ());
inst = flatpak_installation_new_user (NULL, &error);
g_assert_no_error (error);
refs = flatpak_installation_list_remote_related_refs_sync (inst, repo_name, app, NULL, &error);
g_assert_nonnull (refs);
g_assert_no_error (error);
g_assert_cmpint (refs->len, ==, 1);
ref = g_ptr_array_index (refs, 0);
g_assert_cmpstr (flatpak_ref_get_name (FLATPAK_REF (ref)), ==, "org.test.Hello.Locale");
g_assert_true (flatpak_related_ref_should_download (ref));
g_assert_true (flatpak_related_ref_should_delete (ref));
g_assert_false (flatpak_related_ref_should_autoprune (ref));
g_assert (g_strv_length ((char **) flatpak_related_ref_get_subpaths (ref)) == 1);
g_assert_cmpstr (flatpak_related_ref_get_subpaths (ref)[0], ==, "/de");
g_object_get (ref,
"subpaths", &subpaths,
"should-download", &should_download,
"should-delete", &should_delete,
"should-autoprune", &should_autoprune,
NULL);
g_assert (g_strv_length (subpaths) == 1);
g_assert_cmpstr (subpaths[0], ==, "/de");
g_assert_true (should_download);
g_assert_true (should_delete);
g_assert_false (should_autoprune);
// Make the test with extra-languages, instead of languages
clean_languages();
configure_extra_languages();
inst = flatpak_installation_new_user (NULL, &error);
g_assert_no_error (error);
refs = flatpak_installation_list_remote_related_refs_sync (inst, repo_name, app, NULL, &error);
g_assert_nonnull (refs);
g_assert_no_error (error);
g_assert_cmpint (refs->len, ==, 1);
ref = g_ptr_array_index (refs, 0);
g_assert_cmpstr (flatpak_ref_get_name (FLATPAK_REF (ref)), ==, "org.test.Hello.Locale");
g_assert_true (flatpak_related_ref_should_download (ref));
g_assert_true (flatpak_related_ref_should_delete (ref));
g_assert_false (flatpak_related_ref_should_autoprune (ref));
g_assert (g_strv_length ((char **) flatpak_related_ref_get_subpaths (ref)) == 2);
g_assert_cmpstr (flatpak_related_ref_get_subpaths (ref)[0], ==, "/de");
g_assert_cmpstr (flatpak_related_ref_get_subpaths (ref)[1], ==, "/en");
g_object_get (ref,
"subpaths", &subpaths,
"should-download", &should_download,
"should-delete", &should_delete,
"should-autoprune", &should_autoprune,
NULL);
g_assert (g_strv_length (subpaths) == 2);
g_assert_cmpstr (subpaths[0], ==, "/de");
g_assert_cmpstr (subpaths[1], ==, "/en");
g_assert_true (should_download);
g_assert_true (should_delete);
g_assert_false (should_autoprune);
configure_languages();
clean_extra_languages();
}
static void
progress_cb (const char *status,
guint progress,
gboolean estimating,
gpointer user_data)
{
int *count = user_data;
*count += 1;
}
static void
changed_cb (GFileMonitor *monitor,
GFile *file,
GFile *other_file,
GFileMonitorEvent event_type,
gpointer user_data)
{
int *count = user_data;
*count += 1;
}
static gboolean
timeout_cb (gpointer data)
{
gboolean *timeout_reached = data;
*timeout_reached = TRUE;
return G_SOURCE_CONTINUE;
}
static gboolean
check_bwrap_support (void)
{
g_autoptr(GError) error = NULL;
const char *bwrap = g_getenv ("FLATPAK_BWRAP");
if (bwrap != NULL)
{
gint exit_code = 0;
char *argv[] = { (char *) bwrap, "--unshare-ipc", "--unshare-net",
"--unshare-pid", "--ro-bind", "/", "/", "/bin/true", NULL };
g_autofree char *argv_str = g_strjoinv (" ", argv);
g_test_message ("Spawning %s", argv_str);
g_spawn_sync (NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL, &exit_code, &error);
g_assert_no_error (error);
if (exit_code != 0)
return FALSE;
}
return TRUE;
}
static void
test_install_launch_uninstall (void)
{
g_autoptr(FlatpakInstallation) inst = NULL;
g_autoptr(GFileMonitor) monitor = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(FlatpakInstalledRef) ref = NULL;
g_autoptr(FlatpakInstalledRef) runtime_ref = NULL;
FlatpakInstalledRef *ref1 = NULL;
GPtrArray *refs = NULL;
g_autofree char *s = NULL;
g_autofree char *s1 = NULL;
int progress_count, changed_count;
gboolean timeout_reached;
guint timeout_id;
gboolean res;
if (!check_bwrap_support ())
{
g_test_skip ("bwrap not supported");
return;
}
inst = flatpak_installation_new_user (NULL, &error);
g_assert_no_error (error);
monitor = flatpak_installation_create_monitor (inst, NULL, &error);
g_assert_no_error (error);
g_assert (G_IS_FILE_MONITOR (monitor));
g_file_monitor_set_rate_limit (monitor, 100);
g_signal_connect (monitor, "changed", G_CALLBACK (changed_cb), &changed_count);
refs = flatpak_installation_list_installed_refs (inst, NULL, &error);
g_assert_no_error (error);
g_assert_cmpint (refs->len, ==, 0);
g_ptr_array_unref (refs);
changed_count = 0;
progress_count = 0;
timeout_reached = FALSE;
ref = flatpak_installation_install (inst,
repo_name,
FLATPAK_REF_KIND_RUNTIME,
"org.test.Platform",
NULL,
NULL,
progress_cb,
&progress_count,
NULL,
&error);
g_assert_no_error (error);
g_assert (FLATPAK_IS_INSTALLED_REF (ref));
g_assert_cmpint (progress_count, >, 0);
timeout_id = g_timeout_add (20000, timeout_cb, &timeout_reached);
while (!timeout_reached && changed_count == 0)
g_main_context_iteration (NULL, TRUE);
g_source_remove (timeout_id);
g_assert_cmpint (changed_count, >, 0);
g_assert_cmpstr (flatpak_ref_get_name (FLATPAK_REF (ref)), ==, "org.test.Platform");
g_assert_cmpstr (flatpak_ref_get_arch (FLATPAK_REF (ref)), ==, flatpak_get_default_arch ());
g_assert_cmpstr (flatpak_ref_get_branch (FLATPAK_REF (ref)), ==, "master");
g_assert_cmpint (flatpak_ref_get_kind (FLATPAK_REF (ref)), ==, FLATPAK_REF_KIND_RUNTIME);
g_assert_cmpstr (flatpak_ref_get_collection_id (FLATPAK_REF (ref)), ==, repo_collection_id);
g_assert_cmpuint (flatpak_installed_ref_get_installed_size (ref), >, 0);
refs = flatpak_installation_list_installed_refs (inst, NULL, &error);
g_assert_no_error (error);
g_assert_cmpint (refs->len, ==, 1);
ref1 = g_ptr_array_index (refs, 0);
g_assert_cmpstr (flatpak_ref_get_commit (FLATPAK_REF (ref1)), ==, flatpak_ref_get_commit (FLATPAK_REF (ref)));
s = flatpak_ref_format_ref (FLATPAK_REF (ref));
s1 = flatpak_ref_format_ref (FLATPAK_REF (ref1));
g_assert_cmpstr (s, ==, s1);
g_ptr_array_unref (refs);
runtime_ref = g_object_ref (ref);
g_clear_object (&ref);
changed_count = 0;
progress_count = 0;
timeout_reached = FALSE;
ref = flatpak_installation_install (inst,
repo_name,
FLATPAK_REF_KIND_APP,
"org.test.Hello",
NULL,
NULL,
progress_cb,
&progress_count,
NULL,
&error);
g_assert_no_error (error);
g_assert (FLATPAK_IS_INSTALLED_REF (ref));
g_assert_cmpint (progress_count, >, 0);
timeout_id = g_timeout_add (20000, timeout_cb, &timeout_reached);
while (!timeout_reached && changed_count == 0)
g_main_context_iteration (NULL, TRUE);
g_source_remove (timeout_id);
g_assert_cmpint (changed_count, >, 0);
g_assert_cmpstr (flatpak_ref_get_name (FLATPAK_REF (ref)), ==, "org.test.Hello");
g_assert_cmpstr (flatpak_ref_get_arch (FLATPAK_REF (ref)), ==, flatpak_get_default_arch ());
g_assert_cmpstr (flatpak_ref_get_branch (FLATPAK_REF (ref)), ==, "master");
g_assert_cmpint (flatpak_ref_get_kind (FLATPAK_REF (ref)), ==, FLATPAK_REF_KIND_APP);
g_assert_cmpstr (flatpak_ref_get_collection_id (FLATPAK_REF (ref)), ==, repo_collection_id);
g_assert_cmpuint (flatpak_installed_ref_get_installed_size (ref), >, 0);
g_assert_true (flatpak_installed_ref_get_is_current (ref));
refs = flatpak_installation_list_installed_refs (inst, NULL, &error);
g_assert_no_error (error);
g_assert_cmpint (refs->len, ==, 2);
g_ptr_array_unref (refs);
/* first test an error */
res = flatpak_installation_launch (inst, "org.test.Hellooo", NULL, NULL, NULL, NULL, &error);
g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_NOT_INSTALLED);
g_assert_false (res);
g_clear_error (&error);
/* now launch the right thing */
res = flatpak_installation_launch (inst, "org.test.Hello", NULL, NULL, NULL, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
timeout_reached = FALSE;
timeout_id = g_timeout_add (500, timeout_cb, &timeout_reached);
while (!timeout_reached)
g_main_context_iteration (NULL, TRUE);
g_source_remove (timeout_id);
changed_count = 0;
progress_count = 0;
res = flatpak_installation_uninstall (inst,
flatpak_ref_get_kind (FLATPAK_REF (ref)),
flatpak_ref_get_name (FLATPAK_REF (ref)),
flatpak_ref_get_arch (FLATPAK_REF (ref)),
flatpak_ref_get_branch (FLATPAK_REF (ref)),
progress_cb,
&progress_count,
NULL,
&error);
g_assert_no_error (error);
g_assert_true (res);
//FIXME: no progress for uninstall
//g_assert_cmpint (progress_count, >, 0);
timeout_reached = FALSE;
timeout_id = g_timeout_add (500, timeout_cb, &timeout_reached);
while (!timeout_reached && changed_count == 0)
g_main_context_iteration (NULL, TRUE);
g_source_remove (timeout_id);
refs = flatpak_installation_list_installed_refs (inst, NULL, &error);
g_assert_no_error (error);
g_assert_cmpint (refs->len, ==, 1);
g_ptr_array_unref (refs);
changed_count = 0;
progress_count = 0;
res = flatpak_installation_uninstall (inst,
flatpak_ref_get_kind (FLATPAK_REF (runtime_ref)),
flatpak_ref_get_name (FLATPAK_REF (runtime_ref)),
flatpak_ref_get_arch (FLATPAK_REF (runtime_ref)),
flatpak_ref_get_branch (FLATPAK_REF (runtime_ref)),
progress_cb,
&progress_count,
NULL,
&error);
g_assert_no_error (error);
g_assert_true (res);
//FIXME: no progress for uninstall
//g_assert_cmpint (progress_count, >, 0);
timeout_reached = FALSE;
timeout_id = g_timeout_add (500, timeout_cb, &timeout_reached);
while (!timeout_reached && changed_count == 0)
g_main_context_iteration (NULL, TRUE);
g_source_remove (timeout_id);
refs = flatpak_installation_list_installed_refs (inst, NULL, &error);
g_assert_no_error (error);
g_assert_cmpint (refs->len, ==, 0);
g_ptr_array_unref (refs);
}
static void update_test_app (void);
static void update_repo (const char *update_repo_name);
static const char *
flatpak_deploy_data_get_origin (GVariant *deploy_data)
{
const char *origin;
g_variant_get_child (deploy_data, 0, "&s", &origin);
return origin;
}
static const char *
flatpak_deploy_data_get_commit (GVariant *deploy_data)
{
const char *commit;
g_variant_get_child (deploy_data, 1, "&s", &commit);
return commit;
}
static const char *
flatpak_deploy_data_get_runtime (GVariant *deploy_data)
{
g_autoptr(GVariant) metadata = g_variant_get_child_value (deploy_data, 4);
const char *runtime = NULL;
g_variant_lookup (metadata, "runtime", "&s", &runtime);
return runtime;
}
/**
* flatpak_deploy_data_get_subpaths:
*
* Returns: (array length=length zero-terminated=1) (transfer container): an array of constant strings
**/
static const char **
flatpak_deploy_data_get_subpaths (GVariant *deploy_data)
{
const char **subpaths;
g_variant_get_child (deploy_data, 2, "^a&s", &subpaths);
return subpaths;
}
static guint64
flatpak_deploy_data_get_installed_size (GVariant *deploy_data)
{
guint64 size;
g_variant_get_child (deploy_data, 3, "t", &size);
return GUINT64_FROM_BE (size);
}
static GVariant *
flatpak_dir_new_deploy_data (const char *origin,
const char *commit,
char **subpaths,
guint64 installed_size,
GVariant *metadata)
{
char *empty_subpaths[] = {NULL};
GVariantBuilder builder;
if (metadata == NULL)
{
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
metadata = g_variant_builder_end (&builder);
}
return g_variant_ref_sink (g_variant_new ("(ss^ast@a{sv})",
origin,
commit,
subpaths ? subpaths : empty_subpaths,
GUINT64_TO_BE (installed_size),
metadata));
}
#define FLATPAK_DEPLOY_DATA_GVARIANT_STRING "(ssasta{sv})"
#define FLATPAK_DEPLOY_DATA_GVARIANT_FORMAT G_VARIANT_TYPE (FLATPAK_DEPLOY_DATA_GVARIANT_STRING)
static GVariant *
flatpak_load_deploy_data (GFile *deploy_dir)
{
g_autoptr(GFile) data_file = NULL;
g_autoptr(GError) error = NULL;
char *data = NULL;
gsize data_size;
data_file = g_file_get_child (deploy_dir, "deploy");
g_file_load_contents (data_file, NULL, &data, &data_size, NULL, &error);
g_assert_no_error (error);
return g_variant_ref_sink (g_variant_new_from_data (FLATPAK_DEPLOY_DATA_GVARIANT_FORMAT,
data, data_size,
FALSE, g_free, data));
}
static gboolean
flatpak_variant_save (GFile *dest,
GVariant *variant,
GCancellable *cancellable,
GError **error)
{
g_autoptr(GOutputStream) out = NULL;
gsize bytes_written;
out = (GOutputStream *) g_file_replace (dest, NULL, FALSE,
G_FILE_CREATE_REPLACE_DESTINATION,
cancellable, error);
if (out == NULL)
return FALSE;
if (!g_output_stream_write_all (out,
g_variant_get_data (variant),
g_variant_get_size (variant),
&bytes_written,
cancellable,
error))
return FALSE;
if (!g_output_stream_close (out, cancellable, error))
return FALSE;
return TRUE;
}
static void
mangle_deploy_file (FlatpakInstalledRef *ref)
{
g_autoptr(GFile) dir = NULL;
g_autoptr(GVariant) data = NULL;
g_autoptr(GVariant) new_data = NULL;
g_autoptr(GFile) deploy_data_file = NULL;
GVariantBuilder metadata_builder;
g_autoptr(GError) error = NULL;
const char * const previous_ids[] = { "net.example.Goodbye", NULL };
dir = g_file_new_for_path (flatpak_installed_ref_get_deploy_dir (ref));
data = flatpak_load_deploy_data (dir);
g_variant_builder_init (&metadata_builder, G_VARIANT_TYPE ("a{sv}"));
g_variant_builder_add (&metadata_builder, "{s@v}", "runtime",
g_variant_new_variant (g_variant_new_string (flatpak_deploy_data_get_runtime (data))));
g_variant_builder_add (&metadata_builder, "{s@v}", "previous-ids",
g_variant_new_variant (g_variant_new_strv (previous_ids, -1)));
new_data = flatpak_dir_new_deploy_data (flatpak_deploy_data_get_origin (data),
flatpak_deploy_data_get_commit (data),
(char **) flatpak_deploy_data_get_subpaths (data),
flatpak_deploy_data_get_installed_size (data),
g_variant_builder_end (&metadata_builder));
deploy_data_file = g_file_get_child (dir, "deploy");
flatpak_variant_save (deploy_data_file, new_data, NULL, &error);
g_assert_no_error (error);
}
static void
check_desktop_file (FlatpakInstalledRef *ref,
const char *file,
const char *expected_renamed_from)
{
g_autofree char *path = g_build_path (G_DIR_SEPARATOR_S,
flatpak_installed_ref_get_deploy_dir (ref),
"export",
"share",
"applications",
file,
NULL);
g_autoptr(GKeyFile) kf = g_key_file_new ();
g_autofree char *renamed_from = NULL;
g_autoptr(GError) error = NULL;
g_key_file_load_from_file (kf, path, G_KEY_FILE_NONE, &error);
g_assert_no_error (error);
renamed_from = g_key_file_get_value (kf,
G_KEY_FILE_DESKTOP_GROUP,
"X-Flatpak-RenamedFrom",
&error);
g_assert_no_error (error);
g_assert_cmpstr (renamed_from, ==, expected_renamed_from);
}
static void
test_list_updates (void)
{
g_autoptr(FlatpakInstallation) inst = NULL;
g_autoptr(FlatpakTransaction) transaction = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(FlatpakInstalledRef) ref = NULL;
g_autoptr(GPtrArray) refs = NULL;
FlatpakInstalledRef *update_ref = NULL;
g_autoptr(FlatpakInstalledRef) updated_ref = NULL;
g_autofree gchar *app = NULL;
g_autofree gchar *runtime = NULL;
gboolean res;
app = g_strdup_printf ("app/org.test.Hello/%s/master",
flatpak_get_default_arch ());
runtime = g_strdup_printf ("runtime/org.test.Platform/%s/master",
flatpak_get_default_arch ());
inst = flatpak_installation_new_user (NULL, &error);
g_assert_no_error (error);
empty_installation (inst);
transaction = flatpak_transaction_new_for_installation (inst, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (transaction);
/* install org.test.Hello, and have org.test.Hello.Locale and org.test.Platform
* added as deps/related
*/
res = flatpak_transaction_add_install (transaction, repo_name, app, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
res = flatpak_transaction_run (transaction, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
g_clear_object (&transaction);
refs = flatpak_installation_list_installed_refs (inst, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (refs);
g_assert_cmpint (refs->len, ==, 3);
g_clear_pointer (&refs, g_ptr_array_unref);
ref = flatpak_installation_get_installed_ref (inst,
FLATPAK_REF_KIND_APP,
"org.test.Hello",
flatpak_get_default_arch (),
"master", NULL, &error);
g_assert_nonnull (ref);
g_assert_no_error (error);
/* Add a previous-id to the deploy file */
mangle_deploy_file (ref);
/* Update the test app and list the update */
update_test_app ();
update_repo ("test");
/* Drop all in-memory summary caches so we can find the new update */
flatpak_installation_drop_caches (inst, NULL, &error);
g_assert_no_error (error);
refs = flatpak_installation_list_installed_refs_for_update (inst, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (refs);
g_assert_cmpint (refs->len, ==, 2);
update_ref = g_ptr_array_index (refs, 0);
g_assert_cmpstr (flatpak_ref_get_name (FLATPAK_REF (update_ref)), ==, "org.test.Hello");
g_assert_cmpint (flatpak_ref_get_kind (FLATPAK_REF (update_ref)), ==, FLATPAK_REF_KIND_APP);
update_ref = g_ptr_array_index (refs, 1);
g_assert_cmpstr (flatpak_ref_get_name (FLATPAK_REF (update_ref)), ==, "org.test.Hello.Locale");
g_assert_cmpint (flatpak_ref_get_kind (FLATPAK_REF (update_ref)), ==, FLATPAK_REF_KIND_RUNTIME);
/* Install the new update */
updated_ref = flatpak_installation_update (inst,
FLATPAK_UPDATE_FLAGS_NONE,
FLATPAK_REF_KIND_APP,
"org.test.Hello",
flatpak_get_default_arch (), "master",
NULL, NULL, NULL, &error);
g_assert_no_error (error);
g_assert_true (FLATPAK_IS_INSTALLED_REF (updated_ref));
check_desktop_file (updated_ref,
"org.test.Hello.desktop",
"net.example.Goodbye.desktop;");
check_desktop_file (updated_ref,
"org.test.Hello.Again.desktop",
"hello-again.desktop;net.example.Goodbye.Again.desktop;");
/* Uninstall the runtime and app */
transaction = flatpak_transaction_new_for_installation (inst, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (transaction);
res = flatpak_transaction_add_uninstall (transaction, app, &error);
g_assert_no_error (error);
g_assert_true (res);
res = flatpak_transaction_add_uninstall (transaction, runtime, &error);
g_assert_no_error (error);
g_assert_true (res);
res = flatpak_transaction_run (transaction, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
}
static void
test_list_updates_offline (void)
{
g_autoptr(FlatpakInstallation) inst = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(GPtrArray) refs = NULL;
g_autoptr(FlatpakInstalledRef) runtime_ref = NULL;
g_autoptr(FlatpakRemote) remote = NULL;
gboolean res;
g_autofree char *saved_url = NULL;
g_autofree char *wrong_url = NULL;
inst = flatpak_installation_new_user (NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (inst);
/* Install a runtime */
runtime_ref = flatpak_installation_install (inst,
repo_name,
FLATPAK_REF_KIND_RUNTIME,
"org.test.Platform",
NULL, NULL, NULL, NULL, NULL,
&error);
g_assert_no_error (error);
g_assert (FLATPAK_IS_INSTALLED_REF (runtime_ref));
/* Note: here we could create an update for the runtime, but it won't be
* found anyway since the URL will be wrong.
*/
/* Make the URL wrong to simulate being offline */
remote = flatpak_installation_get_remote_by_name (inst, repo_name, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (remote);
saved_url = flatpak_remote_get_url (remote);
wrong_url = g_strdup_printf ("http://127.0.0.1:%s/nonexistent", httpd_port);
flatpak_remote_set_url (remote, wrong_url);
res = flatpak_installation_modify_remote (inst, remote, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
/* Listing updates offline should return an empty array */
refs = flatpak_installation_list_installed_refs_for_update (inst, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (refs);
g_assert_cmpint (refs->len, ==, 0);
/* Restore the correct URL to the remote */
flatpak_remote_set_url (remote, saved_url);
res = flatpak_installation_modify_remote (inst, remote, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
/* Uninstall the runtime */
res = flatpak_installation_uninstall (inst,
flatpak_ref_get_kind (FLATPAK_REF (runtime_ref)),
flatpak_ref_get_name (FLATPAK_REF (runtime_ref)),
flatpak_ref_get_arch (FLATPAK_REF (runtime_ref)),
flatpak_ref_get_branch (FLATPAK_REF (runtime_ref)),
NULL, NULL, NULL,
&error);
g_assert_no_error (error);
g_assert_true (res);
}
static void
run_test_subprocess (char **argv,
RunTestSubprocessFlags flags)
{
int status;
g_autoptr(GError) error = NULL;
g_autofree char *argv_str = g_strjoinv (" ", argv);
g_autofree char *output = NULL;
g_autofree char *errors = NULL;
g_test_message ("Spawning %s", argv_str);
if (flags & RUN_TEST_SUBPROCESS_NO_CAPTURE)
g_spawn_sync (NULL, argv, NULL, G_SPAWN_SEARCH_PATH | G_SPAWN_STDOUT_TO_DEV_NULL, NULL, NULL, NULL, NULL, &status, &error);
else
g_spawn_sync (NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, &output, &errors, &status, &error);
g_assert_no_error (error);
if (output != NULL && output[0] != '\0')
{
g_autofree char *escaped = g_strescape (output, NULL);
g_test_message ("\"%s\" stdout: %s", argv_str, escaped);
}
if (errors != NULL && errors[0] != '\0')
{
g_autofree char *escaped = g_strescape (errors, NULL);
g_test_message ("\"%s\" stderr: %s", argv_str, escaped);
}
g_test_message ("\"%s\" wait status: %d", argv_str, status);
if (WIFEXITED (status))
g_test_message ("\"%s\" exited %d", argv_str, WEXITSTATUS (status));
if (WIFSIGNALED (status))
g_test_message ("\"%s\" killed by signal %d", argv_str, WTERMSIG (status));
if (g_spawn_check_exit_status (status, &error))
return;
else if (flags & RUN_TEST_SUBPROCESS_IGNORE_FAILURE)
g_test_message ("\"%s\" failed: %s", argv_str, error->message);
else
g_assert_no_error (error);
}
static void
make_bundle (void)
{
g_autofree char *repo_url = g_strdup_printf ("http://127.0.0.1:%s/test", httpd_port);
g_autofree char *arg2 = g_strdup_printf ("--repo-url=%s", repo_url);
g_autofree char *path = g_build_filename (testdir, "bundles", NULL);
g_autofree char *file = g_build_filename (path, "hello.flatpak", NULL);
char *argv[] = { "flatpak", "build-bundle", "repo-url", "repos/test", "filename", "org.test.Hello", NULL };
argv[2] = arg2;
argv[4] = file;
g_debug ("Making dir %s", path);
g_mkdir_with_parents (path, S_IRWXU | S_IRWXG | S_IRWXO);
run_test_subprocess (argv, RUN_TEST_SUBPROCESS_DEFAULT);
}
static void
make_test_runtime (const char *runtime_repo_name)
{
g_autofree char *arg0 = NULL;
g_autofree char *arg1 = NULL;
char *argv[] = {
NULL, NULL, "org.test.Platform", "master", "", NULL
};
arg0 = g_test_build_filename (G_TEST_DIST, "make-test-runtime.sh", NULL);
arg1 = g_strdup_printf ("repos/%s", runtime_repo_name);
argv[0] = arg0;
argv[1] = arg1;
argv[4] = repo_collection_id;
run_test_subprocess (argv, RUN_TEST_SUBPROCESS_DEFAULT);
}
static void
make_test_app (const char *app_repo_name)
{
g_autofree char *arg0 = NULL;
g_autofree char *arg1 = NULL;
char *argv[] = { NULL, NULL, "", "master", "", NULL };
arg0 = g_test_build_filename (G_TEST_DIST, "make-test-app.sh", NULL);
arg1 = g_strdup_printf ("repos/%s", app_repo_name);
argv[0] = arg0;
argv[1] = arg1;
argv[4] = repo_collection_id;
run_test_subprocess (argv, RUN_TEST_SUBPROCESS_DEFAULT);
}
static void
update_test_app (void)
{
g_autofree char *arg0 = NULL;
char *argv[] = { NULL, "repos/test", "", "master", "", "SPIN", NULL };
arg0 = g_test_build_filename (G_TEST_DIST, "make-test-app.sh", NULL);
argv[0] = arg0;
argv[4] = repo_collection_id;
run_test_subprocess (argv, RUN_TEST_SUBPROCESS_DEFAULT);
}
static void
update_repo (const char *update_repo_name)
{
g_autofree char *arg4 = NULL;
char *argv[] = { "flatpak", "build-update-repo", "--gpg-homedir=", "--gpg-sign=", NULL, NULL };
g_auto(GStrv) gpgargs = NULL;
gpgargs = g_strsplit (gpg_args, " ", 0);
arg4 = g_strdup_printf ("repos/%s", update_repo_name);
argv[2] = gpgargs[0];
argv[3] = gpgargs[1];
argv[4] = arg4;
run_test_subprocess (argv, RUN_TEST_SUBPROCESS_DEFAULT);
}
static void
launch_httpd (void)
{
g_autoptr(GError) error = NULL;
g_autofree char *port = NULL;
g_autofree char *pid = NULL;
g_autofree char *path = g_test_build_filename (G_TEST_DIST, "test-webserver.sh", NULL);
char *argv[] = {path, "repos", NULL };
/* The web server puts itself in the background, so we can't wait
* for EOF on its stdout, stderr */
run_test_subprocess (argv, RUN_TEST_SUBPROCESS_NO_CAPTURE);
g_file_get_contents ("httpd-pid", &pid, NULL, &error);
g_assert_no_error (error);
httpd_pid = atoi (pid);
g_assert_cmpint (httpd_pid, !=, 0);
g_file_get_contents ("httpd-port", &port, NULL, &error);
g_assert_no_error (error);
if (port[strlen (port) - 1] == '\n')
port[strlen (port) - 1] = '\0';
httpd_port = g_strdup (port);
}
static void
_add_remote (const char *remote_repo_name,
gboolean system)
{
char *argv[] = { "flatpak", "remote-add", NULL, "--gpg-import=", "--collection-id=", "name", "url", NULL };
g_autofree char *gpgimport = NULL;
g_autofree char *collection_id_arg = NULL;
g_autofree char *remote_name = NULL;
gpgimport = g_strdup_printf ("--gpg-import=%s/pubring.gpg", gpg_homedir);
repo_url = g_strdup_printf ("http://127.0.0.1:%s/%s", httpd_port, remote_repo_name);
collection_id_arg = g_strdup_printf ("--collection-id=%s", repo_collection_id);
remote_name = g_strdup_printf ("%s-repo", remote_repo_name);
argv[2] = system ? "--system" : "--user";
argv[3] = gpgimport;
argv[4] = collection_id_arg;
argv[5] = remote_name;
argv[6] = repo_url;
run_test_subprocess (argv, RUN_TEST_SUBPROCESS_DEFAULT);
}
static void
add_remote_system (const char *remote_repo_name)
{
_add_remote (remote_repo_name, TRUE);
}
static void
add_remote_user (const char *remote_repo_name)
{
_add_remote (remote_repo_name, FALSE);
}
static void
_remove_remote (const char *remote_repo_name,
gboolean system)
{
char *argv[] = { "flatpak", "remote-delete", NULL, "name", NULL };
g_autofree char *remote_name = NULL;
remote_name = g_strdup_printf ("%s-repo", remote_repo_name);
argv[2] = system ? "--system" : "--user";
argv[3] = remote_name;
run_test_subprocess (argv, RUN_TEST_SUBPROCESS_DEFAULT);
}
static void
remove_remote_system (const char *remote_repo_name)
{
_remove_remote (remote_repo_name, TRUE);
}
static void
remove_remote_user (const char *remote_repo_name)
{
_remove_remote (remote_repo_name, FALSE);
}
static void
add_flatpakrepo (const char *flatpakrepo_repo_name)
{
g_autofree char *data = NULL;
g_autoptr(GError) error = NULL;
g_autofree char *file_path = NULL;
data = g_strconcat ("[Flatpak Repo]\n"
"Version=1\n"
"Url=http://127.0.0.1:", httpd_port, "/", flatpakrepo_repo_name, "\n"
"DefaultBranch=master\n"
"Title=Test repo\n", NULL);
file_path = g_strdup_printf ("repos/%s/%s-repo.flatpakrepo", flatpakrepo_repo_name, flatpakrepo_repo_name);
g_file_set_contents (file_path, data, -1, &error);
g_assert_no_error (error);
}
static void
add_extra_installation (const char *id,
const char *display_name,
const char *storage_type,
const char *priority)
{
g_autofree char *conffile_path = NULL;
g_autofree char *contents_string = NULL;
g_autofree char *path = NULL;
g_autoptr(GPtrArray) contents_array = NULL;
g_autoptr(GError) error = NULL;
path = g_strconcat (testdir, "/system-", id, NULL);
g_mkdir_with_parents (path, S_IRWXU | S_IRWXG | S_IRWXO);
contents_array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
g_ptr_array_add (contents_array,
g_strdup_printf ("[Installation \"%s\"]\n"
"Path=%s",
id, path));
if (display_name != NULL)
g_ptr_array_add (contents_array, g_strdup_printf ("DisplayName=%s", display_name));
if (storage_type != NULL)
g_ptr_array_add (contents_array, g_strdup_printf ("StorageType=%s", storage_type));
if (priority != NULL)
g_ptr_array_add (contents_array, g_strdup_printf ("Priority=%s", priority));
g_ptr_array_add (contents_array, NULL);
contents_string = g_strjoinv ("\n", (char **) contents_array->pdata);
conffile_path = g_strconcat (flatpak_installationsdir, "/", id, ".conf", NULL);
g_file_set_contents (conffile_path, contents_string, -1, &error);
g_assert_no_error (error);
}
static void
setup_multiple_installations (void)
{
flatpak_installationsdir = g_strconcat (flatpak_configdir, "/installations.d", NULL);
g_mkdir_with_parents (flatpak_installationsdir, S_IRWXU | S_IRWXG | S_IRWXO);
add_extra_installation ("extra-installation-1", "Extra system installation 1", "mmc", "10");
add_extra_installation ("extra-installation-2", "Extra system installation 2", "sdcard", "25");
add_extra_installation ("extra-installation-3", NULL, NULL, NULL);
}
static void
setup_repo (void)
{
repo_collection_id = "com.example.Test";
make_test_runtime ("test");
make_test_app ("test");
update_repo ("test");
launch_httpd ();
add_remote_user ("test");
add_flatpakrepo ("test");
configure_languages ();
/* another copy of the same repo, with different url */
g_assert_cmpint (symlink ("test", "repos/copy-of-test"), ==, 0);
/* another repo, with only the app */
make_test_app ("test-without-runtime");
update_repo ("test-without-runtime");
/* another repo, with only the runtime */
make_test_runtime ("test-runtime-only");
update_repo ("test-runtime-only");
add_flatpakrepo ("test-runtime-only");
}
static void
copy_file (const char *src, const char *dest)
{
gchar *buffer = NULL;
gsize length;
g_autoptr(GError) error = NULL;
g_test_message ("copying %s to %s", src, dest);
if (g_file_get_contents (src, &buffer, &length, &error))
g_file_set_contents (dest, buffer, length, &error);
g_assert_no_error (error);
g_free (buffer);
}
static void
copy_gpg (void)
{
char *src;
char *dest;
src = g_test_build_filename (G_TEST_DIST, "test-keyring", "pubring.gpg", NULL);
dest = g_strconcat (gpg_homedir, "/pubring.gpg", NULL);
copy_file (src, dest);
g_free (src);
g_free (dest);
src = g_test_build_filename (G_TEST_DIST, "test-keyring", "secring.gpg", NULL);
dest = g_strconcat (gpg_homedir, "/secring.gpg", NULL);
copy_file (src, dest);
g_free (src);
g_free (dest);
}
GTestDBus *test_bus = NULL;
static void
global_setup (void)
{
g_autofree char *cachedir = NULL;
g_autofree char *configdir = NULL;
g_autofree char *datadir = NULL;
g_autofree char *homedir = NULL;
g_autofree char *services_dir = NULL;
testdir = g_strdup ("/tmp/flatpak-test-XXXXXX");
g_mkdtemp (testdir);
g_test_message ("testdir: %s", testdir);
homedir = g_strconcat (testdir, "/home", NULL);
g_mkdir_with_parents (homedir, S_IRWXU | S_IRWXG | S_IRWXO);
g_setenv ("HOME", homedir, TRUE);
g_test_message ("setting HOME=%s", homedir);
cachedir = g_strconcat (testdir, "/home/cache", NULL);
g_mkdir_with_parents (cachedir, S_IRWXU | S_IRWXG | S_IRWXO);
g_setenv ("XDG_CACHE_HOME", cachedir, TRUE);
g_test_message ("setting XDG_CACHE_HOME=%s", cachedir);
configdir = g_strconcat (testdir, "/home/config", NULL);
g_mkdir_with_parents (configdir, S_IRWXU | S_IRWXG | S_IRWXO);
g_setenv ("XDG_CONFIG_HOME", configdir, TRUE);
g_test_message ("setting XDG_CONFIG_HOME=%s", configdir);
datadir = g_strconcat (testdir, "/home/share", NULL);
g_mkdir_with_parents (datadir, S_IRWXU | S_IRWXG | S_IRWXO);
g_setenv ("XDG_DATA_HOME", datadir, TRUE);
g_test_message ("setting XDG_DATA_HOME=%s", datadir);
flatpak_runtimedir = g_strconcat (testdir, "/runtime", NULL);
g_mkdir_with_parents (flatpak_runtimedir, S_IRWXU | S_IRWXG | S_IRWXO);
g_setenv ("XDG_RUNTIME_DIR", flatpak_runtimedir, TRUE);
g_test_message ("setting XDG_RUNTIME_DIR=%s", flatpak_runtimedir);
flatpak_systemdir = g_strconcat (testdir, "/system", NULL);
g_mkdir_with_parents (flatpak_systemdir, S_IRWXU | S_IRWXG | S_IRWXO);
g_setenv ("FLATPAK_SYSTEM_DIR", flatpak_systemdir, TRUE);
g_test_message ("setting FLATPAK_SYSTEM_DIR=%s", flatpak_systemdir);
flatpak_systemcachedir = g_strconcat (testdir, "/system-cache", NULL);
g_mkdir_with_parents (flatpak_systemcachedir, S_IRWXU | S_IRWXG | S_IRWXO);
g_setenv ("FLATPAK_SYSTEM_CACHE_DIR", flatpak_systemcachedir, TRUE);
g_test_message ("setting FLATPAK_SYSTEM_CACHE_DIR=%s", flatpak_systemcachedir);
flatpak_configdir = g_strconcat (testdir, "/config", NULL);
g_mkdir_with_parents (flatpak_configdir, S_IRWXU | S_IRWXG | S_IRWXO);
g_setenv ("FLATPAK_CONFIG_DIR", flatpak_configdir, TRUE);
g_test_message ("setting FLATPAK_CONFIG_DIR=%s", flatpak_configdir);
gpg_homedir = g_strconcat (testdir, "/gpghome", NULL);
g_mkdir_with_parents (gpg_homedir, S_IRWXU | S_IRWXG | S_IRWXO);
gpg_args = g_strdup_printf ("--gpg-homedir=%s --gpg-sign=%s", gpg_homedir, gpg_id);
g_setenv ("GPGARGS", gpg_args, TRUE);
g_test_message ("setting GPGARGS=%s", gpg_args);
g_reload_user_special_dirs_cache ();
g_assert_cmpstr (g_get_user_cache_dir (), ==, cachedir);
g_assert_cmpstr (g_get_user_config_dir (), ==, configdir);
g_assert_cmpstr (g_get_user_data_dir (), ==, datadir);
g_assert_cmpstr (g_get_user_runtime_dir (), ==, flatpak_runtimedir);
g_setenv ("FLATPAK_SYSTEM_HELPER_ON_SESSION", "1", TRUE);
g_setenv ("LANGUAGE", "en", TRUE);
test_bus = g_test_dbus_new (G_TEST_DBUS_NONE);
services_dir = g_test_build_filename (G_TEST_BUILT, "services", NULL);
g_test_dbus_add_service_dir (test_bus, services_dir);
g_test_dbus_up (test_bus);
copy_gpg ();
setup_multiple_installations ();
setup_repo ();
make_bundle ();
}
static void
global_teardown (void)
{
char *argv[] = { "gpg-connect-agent", "--homedir", "<placeholder>", "killagent", "/bye", NULL };
if (g_getenv ("SKIP_TEARDOWN"))
return;
g_test_dbus_down (test_bus);
argv[2] = gpg_homedir;
if (httpd_pid != -1)
kill (httpd_pid, SIGKILL);
run_test_subprocess (argv, RUN_TEST_SUBPROCESS_IGNORE_FAILURE);
glnx_shutil_rm_rf_at (-1, testdir, NULL, NULL);
g_free (testdir);
}
/* Check some basic transaction getters, without running a transaction
* or adding ops.
*/
static void
test_misc_transaction (void)
{
struct { int op;
const char *name;
} kinds[] = {
{ FLATPAK_TRANSACTION_OPERATION_INSTALL, "install" },
{ FLATPAK_TRANSACTION_OPERATION_UPDATE, "update" },
{ FLATPAK_TRANSACTION_OPERATION_INSTALL_BUNDLE, "install-bundle" },
{ FLATPAK_TRANSACTION_OPERATION_UNINSTALL, "uninstall" },
{ FLATPAK_TRANSACTION_OPERATION_LAST_TYPE, NULL }
};
int i;
g_autoptr(GError) error = NULL;
g_autoptr(FlatpakInstallation) inst = NULL;
g_autoptr(FlatpakInstallation) inst2 = NULL;
g_autoptr(FlatpakInstallation) inst3 = NULL;
g_autoptr(FlatpakTransaction) transaction = NULL;
g_autoptr(FlatpakTransactionOperation) op = NULL;
GList *list = NULL;
for (i = 0; i < G_N_ELEMENTS (kinds); i++)
g_assert_cmpstr (kinds[i].name, ==, flatpak_transaction_operation_type_to_string (kinds[i].op));
inst = flatpak_installation_new_user (NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (inst);
transaction = flatpak_transaction_new_for_installation (NULL, NULL, &error);
g_assert_nonnull (error);
g_assert_null (transaction);
g_clear_error (&error);
transaction = flatpak_transaction_new_for_installation (inst, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (transaction);
g_object_get (transaction, "installation", &inst2, NULL);
g_assert (inst2 == inst);
inst3 = flatpak_transaction_get_installation (transaction);
g_assert (inst3 == inst);
op = flatpak_transaction_get_current_operation (transaction);
g_assert_null (op);
list = flatpak_transaction_get_operations (transaction);
g_assert_null (list);
flatpak_transaction_set_no_deploy (transaction, TRUE);
g_assert (flatpak_transaction_get_no_deploy (transaction) == TRUE);
flatpak_transaction_set_no_pull (transaction, TRUE);
g_assert (flatpak_transaction_get_no_pull (transaction) == TRUE);
g_assert (flatpak_transaction_is_empty (transaction));
}
static void
empty_installation (FlatpakInstallation *inst)
{
g_autoptr(GPtrArray) refs = NULL;
g_autoptr(GError) error = NULL;
int i;
refs = flatpak_installation_list_installed_refs (inst, NULL, &error);
g_assert_no_error (error);
for (i = 0; i < refs->len; i++)
{
FlatpakRef *ref = g_ptr_array_index (refs, i);
flatpak_installation_uninstall_full (inst,
FLATPAK_UNINSTALL_FLAGS_NO_TRIGGERS,
flatpak_ref_get_kind (ref),
flatpak_ref_get_name (ref),
flatpak_ref_get_arch (ref),
flatpak_ref_get_branch (ref),
NULL, NULL, NULL, &error);
g_assert_no_error (error);
}
flatpak_installation_run_triggers (inst, NULL, &error);
g_assert_no_error (error);
flatpak_installation_prune_local_repo (inst, NULL, &error);
g_assert_no_error (error);
}
static int ready_count;
static int new_op_count;
static int op_done_count;
static gboolean
op_error (FlatpakTransaction *transaction,
FlatpakTransactionOperation *op,
GError *error,
FlatpakTransactionErrorDetails *details)
{
g_assert_not_reached ();
return TRUE;
}
static gboolean
choose_remote (FlatpakTransaction *transaction,
const char *ref,
const char *runtime,
const char **remotes)
{
g_assert_cmpint (g_strv_length ((char **) remotes), ==, 1);
return 0;
}
static void
end_of_lifed (FlatpakTransaction *transaction,
const char *ref,
const char *reason,
const char *rebase)
{
g_assert_not_reached ();
}
static gboolean
add_new_remote (FlatpakTransaction *transaction,
FlatpakTransactionRemoteReason reason,
const char *from_id,
const char *suggested_name,
const char *url)
{
g_assert_not_reached ();
return TRUE;
}
static gboolean
ready (FlatpakTransaction *transaction)
{
GList *ops, *l;
ready_count++;
ops = flatpak_transaction_get_operations (transaction);
g_assert_cmpint (g_list_length (ops), ==, 3);
for (l = ops; l; l = l->next)
{
FlatpakTransactionOperation *op = l->data;
g_assert_cmpint (flatpak_transaction_operation_get_operation_type (op), ==, FLATPAK_TRANSACTION_OPERATION_INSTALL);
g_assert_nonnull (flatpak_transaction_operation_get_commit (op));
}
g_list_free_full (ops, g_object_unref);
return TRUE;
}
static void
new_op (FlatpakTransaction *transaction,
FlatpakTransactionOperation *op,
FlatpakTransactionProgress *progress)
{
g_autofree char *status = NULL;
g_autoptr(FlatpakTransactionOperation) current = NULL;
g_auto(GStrv) refs = NULL;
refs = g_new0 (gchar *, 4);
refs[0] = g_strdup_printf ("runtime/org.test.Platform/%s/master",
flatpak_get_default_arch ());
refs[1] = g_strdup_printf ("app/org.test.Hello/%s/master",
flatpak_get_default_arch ());
refs[2] = g_strdup_printf ("runtime/org.test.Hello.Locale/%s/master",
flatpak_get_default_arch ());
refs[3] = NULL;
new_op_count++;
current = flatpak_transaction_get_current_operation (transaction);
g_assert (op == current);
g_assert_cmpint (flatpak_transaction_operation_get_operation_type (op), ==, FLATPAK_TRANSACTION_OPERATION_INSTALL);
g_assert_true (g_strv_contains ((const gchar * const *) refs, flatpak_transaction_operation_get_ref (op)));
status = flatpak_transaction_progress_get_status (progress);
g_assert_cmpstr (status, ==, "Initializing");
g_assert_true (flatpak_transaction_progress_get_is_estimating (progress));
g_assert_cmpint (flatpak_transaction_progress_get_progress (progress), ==, 0);
}
static void
op_done (FlatpakTransaction *transaction,
FlatpakTransactionOperation *op,
const char *commit,
int result)
{
g_auto(GStrv) refs = NULL;
refs = g_new0 (gchar *, 4);
refs[0] = g_strdup_printf ("runtime/org.test.Platform/%s/master",
flatpak_get_default_arch ());
refs[1] = g_strdup_printf ("app/org.test.Hello/%s/master",
flatpak_get_default_arch ());
refs[2] = g_strdup_printf ("runtime/org.test.Hello.Locale/%s/master",
flatpak_get_default_arch ());
refs[3] = NULL;
op_done_count++;
g_assert_cmpint (flatpak_transaction_operation_get_operation_type (op), ==, FLATPAK_TRANSACTION_OPERATION_INSTALL);
g_assert_true (g_strv_contains ((const gchar * const *) refs, flatpak_transaction_operation_get_ref (op)));
g_assert_cmpint (result, ==, 0);
}
static void
op_done_no_change (FlatpakTransaction *transaction,
FlatpakTransactionOperation *op,
const char *commit,
int result)
{
g_autofree char *app = NULL;
app = g_strdup_printf ("app/org.test.Hello/%s/master",
flatpak_get_default_arch ());
g_assert_cmpstr (flatpak_transaction_operation_get_ref (op), ==, app);
g_assert_cmpint (flatpak_transaction_operation_get_operation_type (op), ==, FLATPAK_TRANSACTION_OPERATION_UPDATE);
g_assert_cmpint (result, ==, FLATPAK_TRANSACTION_RESULT_NO_CHANGE);
}
static void
op_done_with_change (FlatpakTransaction *transaction,
FlatpakTransactionOperation *op,
const char *commit,
int result)
{
g_autofree char *app = NULL;
app = g_strdup_printf ("app/org.test.Hello/%s/master",
flatpak_get_default_arch ());
g_assert_cmpstr (flatpak_transaction_operation_get_ref (op), ==, app);
g_assert_cmpint (flatpak_transaction_operation_get_operation_type (op), ==, FLATPAK_TRANSACTION_OPERATION_UPDATE);
g_assert_cmpint (result, ==, 0);
}
/* Do a bunch of installs and uninstalls with a transaction, and check
* that ops looks as expected, and that signal are fired.
*/
static void
test_transaction_install_uninstall (void)
{
g_autoptr(FlatpakInstallation) inst = NULL;
g_autoptr(FlatpakTransaction) transaction = NULL;
g_autoptr(FlatpakTransactionOperation) op = NULL;
gboolean res;
g_autoptr(GError) error = NULL;
GList *list;
g_autoptr(GPtrArray) refs = NULL;
g_autoptr(FlatpakInstalledRef) ref = NULL;
gboolean is_current;
g_autofree char *origin = NULL;
guint64 size;
g_auto(GStrv) subpaths = NULL;
g_autofree char *eol = NULL;
g_autofree char *eol_rebase = NULL;
g_autofree char *commit = NULL;
g_autofree char *deploy = NULL;
GBytes *bytes = NULL;
const char *empty_subpaths[] = { "", NULL };
g_autofree char *app = NULL;
g_autofree char *runtime = NULL;
app = g_strdup_printf ("app/org.test.Hello/%s/master",
flatpak_get_default_arch ());
runtime = g_strdup_printf ("runtime/org.test.Platform/%s/master",
flatpak_get_default_arch ());
inst = flatpak_installation_new_user (NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (inst);
/* start from a clean slate */
empty_installation (inst);
/* Check that it is indeed empty */
ref = flatpak_installation_get_current_installed_app (inst, "org.test.Hello", NULL, &error);
g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_NOT_INSTALLED);
g_assert_null (ref);
g_clear_error (&error);
/* update org.test.Hello, we expect a non-installed error */
transaction = flatpak_transaction_new_for_installation (inst, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (transaction);
g_assert (flatpak_transaction_is_empty (transaction));
res = flatpak_transaction_add_update (transaction, app, NULL, NULL, &error);
g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_NOT_INSTALLED);
g_assert_false (res);
g_clear_error (&error);
g_clear_object (&transaction);
/* install org.test.Hello, and have org.test.Hello.Locale and org.test.Platform
* added as deps/related
*/
transaction = flatpak_transaction_new_for_installation (inst, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (transaction);
res = flatpak_transaction_add_install (transaction, repo_name, app, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
g_assert (!flatpak_transaction_is_empty (transaction));
list = flatpak_transaction_get_operations (transaction);
g_assert_cmpint (g_list_length (list), ==, 1);
op = (FlatpakTransactionOperation *) list->data;
g_list_free (list);
g_assert_cmpint (flatpak_transaction_operation_get_operation_type (op), ==, FLATPAK_TRANSACTION_OPERATION_INSTALL);
g_assert_cmpstr (flatpak_transaction_operation_get_ref (op), ==, app);
g_assert_cmpstr (flatpak_transaction_operation_get_remote (op), ==, repo_name);
g_assert_null (flatpak_transaction_operation_get_bundle_path (op));
g_assert_null (flatpak_transaction_operation_get_commit (op));
g_signal_connect (transaction, "ready", G_CALLBACK (ready), NULL);
g_signal_connect (transaction, "new-operation", G_CALLBACK (new_op), NULL);
g_signal_connect (transaction, "operation-done", G_CALLBACK (op_done), NULL);
g_signal_connect (transaction, "operation-error", G_CALLBACK (op_error), NULL);
g_signal_connect (transaction, "choose-remote-for-ref", G_CALLBACK (choose_remote), NULL);
g_signal_connect (transaction, "end-of-lifed", G_CALLBACK (end_of_lifed), NULL);
g_signal_connect (transaction, "add-new-remote", G_CALLBACK (add_new_remote), NULL);
ready_count = 0;
new_op_count = 0;
op_done_count = 0;
res = flatpak_transaction_run (transaction, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
g_assert_cmpint (ready_count, ==, 1);
g_assert_cmpint (new_op_count, ==, 3);
g_assert_cmpint (op_done_count, ==, 3);
refs = flatpak_installation_list_installed_refs (inst, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (refs);
g_assert_cmpint (refs->len, ==, 3);
g_clear_pointer (&refs, g_ptr_array_unref);
ref = flatpak_installation_get_current_installed_app (inst, "org.test.Hello", NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (ref);
g_assert_cmpstr (flatpak_installed_ref_get_origin (ref), ==, repo_name);
g_assert_null (flatpak_installed_ref_get_subpaths (ref));
g_assert_cmpuint (flatpak_installed_ref_get_installed_size (ref), >, 0);
g_assert_true (flatpak_installed_ref_get_is_current (ref));
g_assert_nonnull (flatpak_installed_ref_get_latest_commit (ref));
g_assert_nonnull (flatpak_installed_ref_get_deploy_dir (ref));
g_assert_null (flatpak_installed_ref_get_eol (ref));
g_assert_null (flatpak_installed_ref_get_eol_rebase (ref));
g_assert_cmpstr (flatpak_installed_ref_get_appdata_name (ref), ==, "Hello world test app: org.test.Hello");
g_assert_cmpstr (flatpak_installed_ref_get_appdata_summary (ref), ==, "Print a greeting");
g_assert_cmpstr (flatpak_installed_ref_get_appdata_version (ref), ==, "0.0.1");
g_object_get (ref,
"is-current", &is_current,
"origin", &origin,
"installed-size", &size,
"latest-commit", &commit,
"deploy-dir", &deploy,
"subpaths", &subpaths,
"end-of-life", &eol,
"end-of-life-rebase", &eol_rebase,
NULL);
g_assert_true (is_current);
g_assert_cmpstr (origin, ==, repo_name);
g_assert_cmpuint (size, >, 0);
g_assert_nonnull (commit);
g_assert_nonnull (deploy);
g_assert_null (subpaths);
g_assert_null (eol);
g_assert_null (eol_rebase);
g_clear_object (&ref);
refs = flatpak_installation_list_installed_refs_by_kind (inst,
FLATPAK_REF_KIND_RUNTIME,
NULL,
&error);
g_assert_no_error (error);
g_assert_cmpint (refs->len, ==, 2);
ref = g_object_ref (g_ptr_array_index (refs, 0));
bytes = flatpak_installed_ref_load_metadata (ref, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (bytes);
g_bytes_unref (bytes);
g_clear_object (&ref);
g_clear_pointer (&refs, g_ptr_array_unref);
g_clear_object (&transaction);
/* install org.test.Hello again. we expect an already-installed error */
transaction = flatpak_transaction_new_for_installation (inst, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (transaction);
res = flatpak_transaction_add_install (transaction, repo_name, app, NULL, &error);
g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_ALREADY_INSTALLED);
g_assert_false (res);
g_clear_error (&error);
g_clear_object (&transaction);
/* uninstall org.test.Hello, we expect org.test.Hello.Locale to be
* removed with it, but org.test.Platform to stay
*/
transaction = flatpak_transaction_new_for_installation (inst, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (transaction);
res = flatpak_transaction_add_uninstall (transaction, app, &error);
g_assert_no_error (error);
g_assert_true (res);
res = flatpak_transaction_run (transaction, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
refs = flatpak_installation_list_installed_refs (inst, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (refs);
g_assert_cmpint (refs->len, ==, 1);
ref = g_object_ref (g_ptr_array_index (refs, 0));
g_assert_cmpstr (flatpak_ref_get_name (FLATPAK_REF (ref)), ==, "org.test.Platform");
g_clear_object (&ref);
g_clear_pointer (&refs, g_ptr_array_unref);
/* run the transaction again, expect an error */
res = flatpak_transaction_run (transaction, NULL, &error);
g_assert_nonnull (error);
g_assert_false (res);
g_clear_error (&error);
g_clear_object (&transaction);
/* install org.test.Hello and uninstall org.test.Platform. This is
* expected to yield an error
*/
transaction = flatpak_transaction_new_for_installation (inst, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (transaction);
res = flatpak_transaction_add_install (transaction, repo_name, app, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
res = flatpak_transaction_add_uninstall (transaction, runtime, &error);
g_assert_no_error (error);
g_assert_true (res);
res = flatpak_transaction_run (transaction, NULL, &error);
g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_RUNTIME_USED);
g_assert_false (res);
g_clear_error (&error);
g_clear_object (&transaction);
/* try again to install org.test.Hello. We'll end up with 3 refs */
transaction = flatpak_transaction_new_for_installation (inst, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (transaction);
res = flatpak_transaction_add_install (transaction, repo_name, app, empty_subpaths, &error);
g_assert_no_error (error);
g_assert_true (res);
res = flatpak_transaction_run (transaction, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
refs = flatpak_installation_list_installed_refs (inst, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (refs);
g_assert_cmpint (refs->len, ==, 3);
g_clear_pointer (&refs, g_ptr_array_unref);
ref = flatpak_installation_get_installed_ref (inst, FLATPAK_REF_KIND_APP, "org.test.Hello", "xzy", "master", NULL, &error);
g_assert_null (ref);
g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_NOT_INSTALLED);
g_clear_error (&error);
ref = flatpak_installation_get_installed_ref (inst, FLATPAK_REF_KIND_APP, "org.test.Hello", NULL, "master", NULL, &error);
g_assert_nonnull (ref);
g_assert_no_error (error);
g_assert_cmpstr (flatpak_ref_get_name (FLATPAK_REF (ref)), ==, "org.test.Hello");
g_clear_object (&ref);
g_clear_object (&transaction);
/* update org.test.Hello. Check that this is a no-op */
transaction = flatpak_transaction_new_for_installation (inst, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (transaction);
res = flatpak_transaction_add_update (transaction, app, NULL, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
g_signal_connect (transaction, "operation-done", G_CALLBACK (op_done_no_change), NULL);
res = flatpak_transaction_run (transaction, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
g_clear_object (&transaction);
/* update again, using { "", NULL } as subpaths, to install all */
transaction = flatpak_transaction_new_for_installation (inst, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (transaction);
res = flatpak_transaction_add_update (transaction, app, empty_subpaths, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
g_signal_connect (transaction, "operation-done", G_CALLBACK (op_done_with_change), NULL);
res = flatpak_transaction_run (transaction, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
g_clear_object (&transaction);
/* uninstall both org.test.Hello and org.test.Platform, leaving an empty installation */
transaction = flatpak_transaction_new_for_installation (inst, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (transaction);
res = flatpak_transaction_add_uninstall (transaction, app, &error);
g_assert_no_error (error);
g_assert_true (res);
res = flatpak_transaction_add_uninstall (transaction, runtime, &error);
g_assert_no_error (error);
g_assert_true (res);
res = flatpak_transaction_run (transaction, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
/* uninstall again, expect a not-installed error */
transaction = flatpak_transaction_new_for_installation (inst, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (transaction);
res = flatpak_transaction_add_uninstall (transaction, app, &error);
g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_NOT_INSTALLED);
g_assert_false (res);
}
static int remote_added;
static gboolean
add_new_remote2 (FlatpakTransaction *transaction,
FlatpakTransactionRemoteReason reason,
const char *from_id,
const char *suggested_name,
const char *url)
{
remote_added++;
g_assert_cmpstr (suggested_name, ==, "my-little-repo");
return TRUE;
}
/* test installing a flatpakref with a transaction */
static void
test_transaction_install_flatpakref (void)
{
g_autoptr(FlatpakInstallation) inst = NULL;
g_autoptr(FlatpakTransaction) transaction = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(GPtrArray) refs = NULL;
gboolean res;
g_autofree char *s = NULL;
g_autoptr(GBytes) data = NULL;
g_autofree char *app = NULL;
g_autofree char *runtime = NULL;
app = g_strdup_printf ("app/org.test.Hello/%s/master",
flatpak_get_default_arch ());
runtime = g_strdup_printf ("runtime/org.test.Platform/%s/master",
flatpak_get_default_arch ());
inst = flatpak_installation_new_user (NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (inst);
/* start from a clean slate */
empty_installation (inst);
transaction = flatpak_transaction_new_for_installation (inst, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (transaction);
/* pointless, but do it anyway */
flatpak_transaction_add_dependency_source (transaction, inst);
data = g_bytes_new ("shoobidoo", strlen ("shoobidoo"));
res = flatpak_transaction_add_install_flatpakref (transaction, data, &error);
g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_INVALID_DATA);
g_clear_error (&error);
g_assert_false (res);
g_clear_pointer (&data, g_bytes_unref);
s = g_strconcat ("[Flatpak Ref]\n"
"Title=Test App\n"
"Name=org.test.Hello\n"
"Branch=master\n"
/* Uses a different url for the repo, so we can ensure it gets added */
"Url=http://127.0.0.1:", httpd_port, "/copy-of-test\n"
"IsRuntime=False\n"
"SuggestRemoteName=my-little-repo\n"
"RuntimeRepo=http://127.0.0.1:", httpd_port, "/test/test-repo.flatpakrepo\n",
NULL);
data = g_bytes_new (s, strlen (s));
res = flatpak_transaction_add_install_flatpakref (transaction, data, &error);
g_assert_no_error (error);
g_assert_true (res);
remote_added = 0;
g_signal_connect (transaction, "add-new-remote", G_CALLBACK (add_new_remote2), NULL);
res = flatpak_transaction_run (transaction, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
g_assert_cmpint (remote_added, >, 0);
refs = flatpak_installation_list_installed_refs (inst, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (refs);
g_assert_cmpint (refs->len, ==, 3);
g_clear_pointer (&refs, g_ptr_array_unref);
transaction = flatpak_transaction_new_for_installation (inst, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (transaction);
res = flatpak_transaction_add_uninstall (transaction, app, &error);
g_assert_no_error (error);
g_assert_true (res);
res = flatpak_transaction_add_uninstall (transaction, runtime, &error);
g_assert_no_error (error);
g_assert_true (res);
res = flatpak_transaction_run (transaction, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
}
static gboolean
_is_remote_in_installation (FlatpakInstallation *installation,
const char *remote_repo_name)
{
g_autoptr(GError) error = NULL;
g_autoptr(GPtrArray) remotes = NULL;
g_autofree char *remote_name = NULL;
remotes = flatpak_installation_list_remotes (installation, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (remotes);
remote_name = g_strdup_printf ("%s-repo", remote_repo_name);
for (guint i = 0; i < remotes->len; ++i)
{
FlatpakRemote *remote = g_ptr_array_index (remotes, i);
if (g_strcmp0 (remote_name, flatpak_remote_get_name (remote)) == 0)
return TRUE;
}
return FALSE;
}
static void
assert_remote_in_installation (FlatpakInstallation *installation,
const char *remote_repo_name)
{
g_assert (_is_remote_in_installation (installation, remote_repo_name));
}
static void
assert_remote_not_in_installation (FlatpakInstallation *installation,
const char *remote_repo_name)
{
g_assert (!_is_remote_in_installation (installation, remote_repo_name));
}
static gboolean
add_new_remote3 (FlatpakTransaction *transaction,
FlatpakTransactionRemoteReason reason,
const char *from_id,
const char *suggested_name,
const char *url)
{
return TRUE;
}
/* Test that installing a flatpakref causes both the origin remote and the
* runtime remote to be created, even if they already exist in another
* installation */
static void
test_transaction_flatpakref_remote_creation (void)
{
g_autoptr(FlatpakInstallation) user_inst = NULL;
g_autoptr(FlatpakInstallation) system_inst = NULL;
g_autoptr(FlatpakTransaction) transaction = NULL;
g_autoptr(GError) error = NULL;
g_autofree char *s = NULL;
g_autoptr(GBytes) data = NULL;
gboolean res;
system_inst = flatpak_installation_new_system (NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (system_inst);
empty_installation (system_inst);
add_remote_system ("test-without-runtime");
add_remote_system ("test-runtime-only");
user_inst = flatpak_installation_new_user (NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (user_inst);
empty_installation (user_inst);
assert_remote_not_in_installation (user_inst, "test-without-runtime");
assert_remote_not_in_installation (user_inst, "test-runtime-only");
transaction = flatpak_transaction_new_for_installation (user_inst, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (transaction);
s = g_strconcat ("[Flatpak Ref]\n"
"Title=Test App\n"
"Name=org.test.Hello\n"
"Branch=master\n"
"Url=http://127.0.0.1:", httpd_port, "/test-without-runtime\n"
"IsRuntime=False\n"
"SuggestRemoteName=test-without-runtime-repo\n"
"RuntimeRepo=http://127.0.0.1:", httpd_port, "/test-runtime-only/test-runtime-only-repo.flatpakrepo\n",
NULL);
data = g_bytes_new (s, strlen (s));
res = flatpak_transaction_add_install_flatpakref (transaction, data, &error);
g_assert_no_error (error);
g_assert_true (res);
g_signal_connect (transaction, "add-new-remote", G_CALLBACK (add_new_remote3), NULL);
res = flatpak_transaction_run (transaction, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
assert_remote_in_installation (user_inst, "test-without-runtime");
assert_remote_in_installation (user_inst, "test-runtime-only");
empty_installation (user_inst);
remove_remote_user ("test-without-runtime");
remove_remote_user ("test-runtime-only");
remove_remote_system ("test-without-runtime");
remove_remote_system ("test-runtime-only");
}
static gboolean
check_ready1_abort (FlatpakTransaction *transaction)
{
GList *ops;
FlatpakTransactionOperation *op;
g_autofree char *app = NULL;
app = g_strdup_printf ("app/org.test.Hello/%s/master",
flatpak_get_default_arch ());
ops = flatpak_transaction_get_operations (transaction);
g_assert_cmpint (g_list_length (ops), ==, 1);
op = ops->data;
g_assert_cmpint (flatpak_transaction_operation_get_operation_type (op), ==, FLATPAK_TRANSACTION_OPERATION_INSTALL);
g_assert_cmpstr (flatpak_transaction_operation_get_ref (op), ==, app);
g_list_free_full (ops, g_object_unref);
return FALSE;
}
static gboolean
check_ready3_abort (FlatpakTransaction *transaction)
{
GList *ops;
FlatpakTransactionOperation *op;
g_autofree char *app = NULL;
g_autofree char *runtime = NULL;
g_autofree char *locale = NULL;
app = g_strdup_printf ("app/org.test.Hello/%s/master",
flatpak_get_default_arch ());
runtime = g_strdup_printf ("runtime/org.test.Platform/%s/master",
flatpak_get_default_arch ());
locale = g_strdup_printf ("runtime/org.test.Hello.Locale/%s/master",
flatpak_get_default_arch ());
ops = flatpak_transaction_get_operations (transaction);
g_assert_cmpint (g_list_length (ops), ==, 3);
op = ops->data;
g_assert_cmpint (flatpak_transaction_operation_get_operation_type (op), ==, FLATPAK_TRANSACTION_OPERATION_INSTALL);
g_assert_cmpstr (flatpak_transaction_operation_get_ref (op), ==, locale);
op = ops->next->data;
g_assert_cmpint (flatpak_transaction_operation_get_operation_type (op), ==, FLATPAK_TRANSACTION_OPERATION_INSTALL);
g_assert_cmpstr (flatpak_transaction_operation_get_ref (op), ==, runtime);
op = ops->next->next->data;
g_assert_cmpint (flatpak_transaction_operation_get_operation_type (op), ==, FLATPAK_TRANSACTION_OPERATION_INSTALL);
g_assert_cmpstr (flatpak_transaction_operation_get_ref (op), ==, app);
g_list_free_full (ops, g_object_unref);
return FALSE;
}
/* test disabling dependencies and related */
static void
test_transaction_deps (void)
{
g_autoptr(FlatpakInstallation) inst = NULL;
g_autoptr(FlatpakTransaction) transaction = NULL;
g_autoptr(GError) error = NULL;
gboolean res;
g_autofree char *app = NULL;
app = g_strdup_printf ("app/org.test.Hello/%s/master",
flatpak_get_default_arch ());
inst = flatpak_installation_new_user (NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (inst);
empty_installation (inst);
transaction = flatpak_transaction_new_for_installation (inst, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (transaction);
flatpak_transaction_set_disable_dependencies (transaction, TRUE);
flatpak_transaction_set_disable_related (transaction, TRUE);
res = flatpak_transaction_add_install (transaction, repo_name, app, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
g_signal_connect (transaction, "ready", G_CALLBACK (check_ready1_abort), NULL);
flatpak_transaction_run (transaction, NULL, &error);
g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_ABORTED);
g_clear_error (&error);
g_clear_object (&transaction);
transaction = flatpak_transaction_new_for_installation (inst, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (transaction);
flatpak_transaction_set_disable_dependencies (transaction, FALSE);
flatpak_transaction_set_disable_related (transaction, FALSE);
res = flatpak_transaction_add_install (transaction, repo_name, app, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
g_signal_connect (transaction, "ready", G_CALLBACK (check_ready3_abort), NULL);
flatpak_transaction_run (transaction, NULL, &error);
g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_ABORTED);
}
/* install from a local repository */
static void
test_transaction_install_local (void)
{
g_autoptr(FlatpakInstallation) inst = NULL;
g_autoptr(FlatpakTransaction) transaction = NULL;
g_autoptr(GError) error = NULL;
gboolean res;
g_autofree char *dir = NULL;
g_autofree char *path = NULL;
g_autofree char *url = NULL;
g_autoptr(FlatpakRemote) remote = NULL;
g_autofree char *app = NULL;
app = g_strdup_printf ("app/org.test.Hello/%s/master",
flatpak_get_default_arch ());
inst = flatpak_installation_new_user (NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (inst);
empty_installation (inst);
transaction = flatpak_transaction_new_for_installation (inst, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (transaction);
dir = g_get_current_dir ();
path = g_build_filename (dir, "repos", "test", NULL);
url = g_strconcat ("file://", path, NULL);
res = flatpak_transaction_add_install (transaction, url, app, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
remote = flatpak_installation_get_remote_by_name (inst, "hello-origin", NULL, &error);
g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_REMOTE_NOT_FOUND);
g_assert_null (remote);
g_clear_error (&error);
res = flatpak_transaction_run (transaction, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
remote = flatpak_installation_get_remote_by_name (inst, "hello-origin", NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (remote);
}
typedef struct
{
GMainLoop *loop;
guint stop_waiting_id;
guint hello_dead_cb_id;
gboolean hello_dead;
} TestInstanceContext;
static gboolean
stop_waiting (gpointer data)
{
TestInstanceContext *context = data;
g_main_loop_quit (context->loop);
context->stop_waiting_id = 0;
return G_SOURCE_REMOVE;
}
static void
hello_dead_cb (GPid pid,
int status,
gpointer data)
{
TestInstanceContext *context = data;
context->hello_dead = TRUE;
context->hello_dead_cb_id = 0;
g_main_loop_quit (context->loop);
}
/* test the instance api: install an app, launch it, get the instance,
* kill it, wait for it to die
*/
static void
test_instance (void)
{
g_autoptr(FlatpakInstallation) inst = NULL;
g_autoptr(FlatpakTransaction) transaction = NULL;
g_autoptr(GError) error = NULL;
gboolean res;
g_autoptr(GPtrArray) instances = NULL;
FlatpakInstance *instance;
GKeyFile *info;
g_autofree char *value = NULL;
int i;
g_autofree char *app = NULL;
g_autofree char *runtime = NULL;
TestInstanceContext context = { NULL, 0, 0, FALSE };
app = g_strdup_printf ("app/org.test.Hello/%s/master",
flatpak_get_default_arch ());
runtime = g_strdup_printf ("runtime/org.test.Platform/%s/master",
flatpak_get_default_arch ());
update_test_app ();
update_repo ("test");
if (!check_bwrap_support ())
{
g_test_skip ("bwrap not supported");
return;
}
inst = flatpak_installation_new_user (NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (inst);
empty_installation (inst);
transaction = flatpak_transaction_new_for_installation (inst, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (transaction);
res = flatpak_transaction_add_install (transaction, repo_name, app, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
flatpak_transaction_run (transaction, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
g_clear_object (&transaction);
res = flatpak_installation_launch_full (inst, FLATPAK_LAUNCH_FLAGS_DO_NOT_REAP,
"org.test.Hello", NULL, NULL, NULL, &instance, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
g_assert_nonnull (instance);
instances = flatpak_instance_get_all ();
for (i = 0; i < instances->len; i++)
{
FlatpakInstance *instance2 = g_ptr_array_index (instances, i);
if (strcmp (flatpak_instance_get_id (instance), flatpak_instance_get_id (instance2)) == 0)
break;
}
g_assert_cmpint (i, <, instances->len);
g_clear_pointer (&instances, g_ptr_array_unref);
g_assert_true (flatpak_instance_is_running (instance));
g_assert_nonnull (flatpak_instance_get_id (instance));
info = flatpak_instance_get_info (instance);
g_assert_nonnull (info);
value = g_key_file_get_string (info, "Application", "name", &error);
g_assert_cmpstr (value, ==, "org.test.Hello");
g_clear_pointer (&value, g_free);
value = g_key_file_get_string (info, "Instance", "instance-id", &error);
g_assert_cmpstr (value, ==, flatpak_instance_get_id (instance));
g_clear_pointer (&value, g_free);
g_assert_cmpstr (flatpak_instance_get_app (instance), ==, "org.test.Hello");
g_assert_cmpstr (flatpak_instance_get_arch (instance), ==,
flatpak_get_default_arch ());
g_assert_cmpstr (flatpak_instance_get_branch (instance), ==, "master");
g_assert_nonnull (flatpak_instance_get_commit (instance));
g_assert_cmpstr (flatpak_instance_get_runtime (instance), ==, runtime);
g_assert_nonnull (flatpak_instance_get_runtime_commit (instance));
g_assert_cmpint (flatpak_instance_get_pid (instance), >, 0);
while (flatpak_instance_get_child_pid (instance) == 0)
g_usleep (10000);
g_assert_cmpint (flatpak_instance_get_child_pid (instance), >, 0);
context.loop = g_main_loop_new (NULL, FALSE);
context.hello_dead = FALSE;
context.hello_dead_cb_id = g_child_watch_add (flatpak_instance_get_pid (instance),
hello_dead_cb, &context);
context.stop_waiting_id = g_timeout_add (5000, stop_waiting, &context);
kill (flatpak_instance_get_child_pid (instance), SIGKILL);
g_main_loop_run (context.loop);
if (context.hello_dead_cb_id != 0)
g_source_remove (context.hello_dead_cb_id);
if (context.stop_waiting_id != 0)
g_source_remove (context.stop_waiting_id);
g_main_loop_unref (context.loop);
g_assert (context.hello_dead);
g_assert_false (flatpak_instance_is_running (instance));
transaction = flatpak_transaction_new_for_installation (inst, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (transaction);
res = flatpak_transaction_add_uninstall (transaction, app, &error);
g_assert_no_error (error);
g_assert_true (res);
res = flatpak_transaction_run (transaction, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
}
static void
test_update_subpaths (void)
{
g_autoptr(FlatpakInstallation) inst = NULL;
g_autoptr(FlatpakInstalledRef) ref = NULL;
gboolean res;
g_autoptr(GError) error = NULL;
g_autoptr(FlatpakTransaction) transaction = NULL;
const char * const *subpaths;
const char * subpaths2[] = { "/de", "/fr", NULL };
g_autofree char *app = NULL;
app = g_strdup_printf ("app/org.test.Hello/%s/master",
flatpak_get_default_arch ());
inst = flatpak_installation_new_user (NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (inst);
empty_installation (inst);
transaction = flatpak_transaction_new_for_installation (inst, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (transaction);
res = flatpak_transaction_add_install (transaction, repo_name, app, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
flatpak_transaction_run (transaction, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
g_clear_object (&transaction);
ref = flatpak_installation_get_installed_ref (inst, FLATPAK_REF_KIND_RUNTIME, "org.test.Hello.Locale", flatpak_get_default_arch (), "master", NULL, &error);
g_assert_no_error (error);
subpaths = flatpak_installed_ref_get_subpaths (ref);
g_assert_cmpint (g_strv_length ((char **) subpaths), ==, 1);
g_assert_cmpstr (subpaths[0], ==, "/de");
g_clear_object (&transaction);
g_clear_object (&ref);
ref = flatpak_installation_update_full (inst, 0, FLATPAK_REF_KIND_RUNTIME, "org.test.Hello.Locale", flatpak_get_default_arch (), "master", subpaths2, NULL, NULL, NULL, &error);
g_assert_no_error (error);
subpaths = flatpak_installed_ref_get_subpaths (ref);
g_assert_cmpint (g_strv_length ((char **) subpaths), ==, 2);
g_assert_cmpstr (subpaths[0], ==, "/de");
g_assert_cmpstr (subpaths[1], ==, "/fr");
}
static void
test_overrides (void)
{
g_autoptr(FlatpakInstallation) inst = NULL;
g_autoptr(GError) error = NULL;
g_autofree char *data = NULL;
g_autoptr(GKeyFile) overrides = NULL;
gboolean res;
g_autofree char *value = NULL;
g_autoptr(FlatpakInstalledRef) ref = NULL;
g_auto(GStrv) list = NULL;
gsize len;
if (!check_bwrap_support ())
{
g_test_skip ("bwrap not supported");
return;
}
/* no library api to set overrides, so... */
const char *argv[] = { "flatpak", "override", "--user",
"--allow=bluetooth",
"--disallow=canbus",
"--device=dri",
"--nodevice=kvm",
"--filesystem=xdg-music",
"--filesystem=~/foo:ro",
"--filesystem=xdg-download/subdir:create",
"--env=FOO=BAR",
"--own-name=foo.bar.baz",
"--talk-name=hello.bla.bla.*",
"--socket=wayland",
"--nosocket=pulseaudio",
"org.test.Hello",
NULL };
run_test_subprocess ((char **) argv, RUN_TEST_SUBPROCESS_DEFAULT);
inst = flatpak_installation_new_user (NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (inst);
empty_installation (inst);
ref = flatpak_installation_update (inst, 0, FLATPAK_REF_KIND_APP, "org.test.Hello", NULL, "master", NULL, NULL, NULL, &error);
g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_NOT_INSTALLED);
g_assert_null (ref);
g_clear_error (&error);
ref = flatpak_installation_install (inst, repo_name, FLATPAK_REF_KIND_APP, "org.test.Hello", NULL, "master", NULL, NULL, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (ref);
ref = flatpak_installation_install (inst, repo_name, FLATPAK_REF_KIND_RUNTIME, "org.test.Platform", NULL, "master", NULL, NULL, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (ref);
res = flatpak_installation_launch (inst, "org.test.Hello", NULL, "master", NULL, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (ref);
data = flatpak_installation_load_app_overrides (inst, "org.test.Hello", NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (data);
overrides = g_key_file_new ();
res = g_key_file_load_from_data (overrides, data, -1, 0, &error);
g_assert_no_error (error);
g_assert_true (res);
value = g_key_file_get_string (overrides, "Context", "devices", &error);
g_assert_cmpstr (value, ==, "dri;!kvm;");
g_clear_pointer (&value, g_free);
value = g_key_file_get_string (overrides, "Context", "features", &error);
g_assert_cmpstr (value, ==, "bluetooth;!canbus;");
g_clear_pointer (&value, g_free);
list = g_key_file_get_string_list (overrides, "Context", "filesystems", &len, &error);
g_assert_cmpint (len, ==, 3);
g_assert_true (g_strv_contains ((const char * const *) list, "xdg-download/subdir:create"));
g_assert_true (g_strv_contains ((const char * const *) list, "xdg-music"));
g_assert_true (g_strv_contains ((const char * const *) list, "~/foo:ro"));
g_clear_pointer (&list, g_strfreev);
list = g_key_file_get_string_list (overrides, "Context", "sockets", &len, &error);
g_assert_cmpint (len, ==, 2);
g_assert_true (g_strv_contains ((const char * const *) list, "wayland"));
g_assert_true (g_strv_contains ((const char * const *) list, "!pulseaudio"));
g_clear_pointer (&list, g_strfreev);
value = g_key_file_get_string (overrides, "Session Bus Policy", "hello.bla.bla.*", &error);
g_assert_cmpstr (value, ==, "talk");
g_clear_pointer (&value, g_free);
value = g_key_file_get_string (overrides, "Session Bus Policy", "foo.bar.baz", &error);
g_assert_cmpstr (value, ==, "own");
g_clear_pointer (&value, g_free);
value = g_key_file_get_string (overrides, "Environment", "FOO", &error);
g_assert_cmpstr (value, ==, "BAR");
g_clear_pointer (&value, g_free);
const char *argv2[] = { "flatpak", "override", "--user", "--reset", "org.test.Hello", NULL };
run_test_subprocess ((char **) argv2, RUN_TEST_SUBPROCESS_DEFAULT);
}
/* basic tests for bundle ref apis */
static void
test_bundle (void)
{
g_autoptr(FlatpakBundleRef) ref = NULL;
g_autoptr(GFile) file = NULL;
g_autoptr(GError) error = NULL;
g_autofree char *path = NULL;
g_autoptr(GFile) file2 = NULL;
g_autofree char *origin = NULL;
g_autofree char *repo_url = g_strdup_printf ("http://127.0.0.1:%s/test", httpd_port);
g_autoptr(GBytes) metadata = NULL;
g_autoptr(GBytes) appstream = NULL;
g_autoptr(GBytes) icon = NULL;
file = g_file_new_for_path ("/dev/null");
ref = flatpak_bundle_ref_new (file, &error);
g_assert_nonnull (error);
g_assert_null (ref);
g_clear_error (&error);
g_clear_object (&file);
path = g_build_filename (testdir, "bundles", "hello.flatpak", NULL);
file = g_file_new_for_path (path);
ref = flatpak_bundle_ref_new (file, &error);
g_assert_no_error (error);
g_assert_nonnull (ref);
g_assert_cmpstr (flatpak_ref_get_name (FLATPAK_REF (ref)), ==, "org.test.Hello");
g_assert_cmpstr (flatpak_ref_get_arch (FLATPAK_REF (ref)), ==, flatpak_get_default_arch ());
g_assert_cmpstr (flatpak_ref_get_branch (FLATPAK_REF (ref)), ==, "master");
g_assert_cmpint (flatpak_ref_get_kind (FLATPAK_REF (ref)), ==, FLATPAK_REF_KIND_APP);
g_assert_cmpstr (flatpak_ref_get_collection_id (FLATPAK_REF (ref)), ==, "com.example.Test");
file2 = flatpak_bundle_ref_get_file (ref);
g_assert (g_file_equal (file, file2));
origin = flatpak_bundle_ref_get_origin (ref);
g_assert_cmpstr (origin, ==, repo_url);
g_assert_null (flatpak_bundle_ref_get_runtime_repo_url (ref));
g_assert_cmpint (flatpak_bundle_ref_get_installed_size (ref), >, 0);
metadata = flatpak_bundle_ref_get_metadata (ref);
g_assert_nonnull (metadata);
/* FIXME verify format */
appstream = flatpak_bundle_ref_get_appstream (ref);
g_assert_nonnull (appstream);
/* FIXME verify format */
icon = flatpak_bundle_ref_get_icon (ref, 64);
g_assert_nonnull (icon);
/* FIXME verify format */
icon = flatpak_bundle_ref_get_icon (ref, 128);
g_assert_null (icon);
g_clear_object (&file2);
g_object_get (ref, "file", &file2, NULL);
g_assert (g_file_equal (file, file2));
}
/* use the installation api to install a bundle */
static void
test_install_bundle (void)
{
g_autoptr(FlatpakInstallation) inst = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(GFile) file = NULL;
g_autofree char *path = NULL;
g_autoptr(FlatpakInstalledRef) ref = NULL;
inst = flatpak_installation_new_user (NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (inst);
empty_installation (inst);
path = g_build_filename (testdir, "bundles", "hello.flatpak", NULL);
file = g_file_new_for_path (path);
ref = flatpak_installation_install_bundle (inst, file, NULL, NULL, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (ref);
}
/* use the installation api to install a flatpakref */
static void
test_install_flatpakref (void)
{
g_autoptr(FlatpakInstallation) inst = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(FlatpakRemoteRef) ref = NULL;
g_autofree char *s = NULL;
g_autoptr(GBytes) data = NULL;
inst = flatpak_installation_new_user (NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (inst);
empty_installation (inst);
s = g_strconcat ("[Flatpak Ref]\n"
"Title=Test App\n"
"Name=org.test.Hello\n"
"Branch=master\n"
"Url=http://127.0.0.1:", httpd_port, "/test\n"
"IsRuntime=False\n"
"SuggestRemoteName=test-repo\n"
"RuntimeRepo=http://127.0.0.1:", httpd_port, "/test/test-repo.flatpakrepo\n",
NULL);
data = g_bytes_new (s, strlen (s));
ref = flatpak_installation_install_ref_file (inst, data, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (ref);
}
/* test the installation method to list installed related refs */
static void
test_list_installed_related_refs (void)
{
g_autoptr(FlatpakInstallation) inst = NULL;
g_autoptr(FlatpakTransaction) transaction = NULL;
g_autoptr(GPtrArray) refs = NULL;
g_autoptr(GError) error = NULL;
FlatpakRelatedRef *ref;
FlatpakInstalledRef *iref;
gboolean res;
g_autofree char *app = NULL;
app = g_strdup_printf ("app/org.test.Hello/%s/master",
flatpak_get_default_arch ());
inst = flatpak_installation_new_user (NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (inst);
empty_installation (inst);
refs = flatpak_installation_list_installed_related_refs_sync (inst, repo_name, app, NULL, &error);
g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_NOT_INSTALLED);
g_assert_null (refs);
g_clear_error (&error);
iref = flatpak_installation_install (inst, repo_name, FLATPAK_REF_KIND_APP, "org.test.Hello", NULL, "master", NULL, NULL, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (iref);
g_clear_object (&iref);
refs = flatpak_installation_list_installed_related_refs_sync (inst, repo_name, app, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (refs);
g_assert_cmpint (refs->len, ==, 0);
g_clear_pointer (&refs, g_ptr_array_unref);
transaction = flatpak_transaction_new_for_installation (inst, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (transaction);
res = flatpak_transaction_add_update (transaction, app, NULL, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
flatpak_transaction_run (transaction, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
g_clear_object (&transaction);
refs = flatpak_installation_list_installed_related_refs_sync (inst, repo_name, app, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (refs);
g_assert_cmpint (refs->len, ==, 1);
ref = g_ptr_array_index (refs, 0);
g_assert_cmpstr (flatpak_ref_get_name (FLATPAK_REF (ref)), ==, "org.test.Hello.Locale");
g_assert_true (flatpak_related_ref_should_download (ref));
g_assert_true (flatpak_related_ref_should_delete (ref));
g_assert_false (flatpak_related_ref_should_autoprune (ref));
g_assert (g_strv_length ((char **) flatpak_related_ref_get_subpaths (ref)) == 1);
g_assert_cmpstr (flatpak_related_ref_get_subpaths (ref)[0], ==, "/de");
// Make the test with extra-languages, instead of languages
clean_languages();
configure_extra_languages();
empty_installation (inst);
refs = flatpak_installation_list_installed_related_refs_sync (inst, repo_name, app, NULL, &error);
g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_NOT_INSTALLED);
g_assert_null (refs);
g_clear_error (&error);
iref = flatpak_installation_install (inst, repo_name, FLATPAK_REF_KIND_APP, "org.test.Hello", NULL, "master", NULL, NULL, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (iref);
g_clear_object (&iref);
refs = flatpak_installation_list_installed_related_refs_sync (inst, repo_name, app, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (refs);
g_assert_cmpint (refs->len, ==, 0);
g_clear_pointer (&refs, g_ptr_array_unref);
transaction = flatpak_transaction_new_for_installation (inst, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (transaction);
res = flatpak_transaction_add_update (transaction, app, NULL, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
flatpak_transaction_run (transaction, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
g_clear_object (&transaction);
refs = flatpak_installation_list_installed_related_refs_sync (inst, repo_name, app, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (refs);
g_assert_cmpint (refs->len, ==, 1);
ref = g_ptr_array_index (refs, 0);
g_assert_cmpstr (flatpak_ref_get_name (FLATPAK_REF (ref)), ==, "org.test.Hello.Locale");
g_assert_true (flatpak_related_ref_should_download (ref));
g_assert_true (flatpak_related_ref_should_delete (ref));
g_assert_false (flatpak_related_ref_should_autoprune (ref));
g_assert (g_strv_length ((char **) flatpak_related_ref_get_subpaths (ref)) == 2);
g_assert_cmpstr (flatpak_related_ref_get_subpaths (ref)[0], ==, "/de");
g_assert_cmpstr (flatpak_related_ref_get_subpaths (ref)[1], ==, "/en");
configure_languages();
clean_extra_languages();
}
static void
test_no_deploy (void)
{
g_autoptr(FlatpakInstallation) inst = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(FlatpakInstalledRef) ref = NULL;
gboolean res;
g_autofree char *app = NULL;
app = g_strdup_printf ("app/org.test.Hello/%s/master",
flatpak_get_default_arch ());
inst = flatpak_installation_new_user (NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (inst);
empty_installation (inst);
ref = flatpak_installation_install_full (inst,
FLATPAK_INSTALL_FLAGS_NO_DEPLOY,
repo_name,
FLATPAK_REF_KIND_APP,
"org.test.Hello",
NULL,
"master",
NULL,
NULL,
NULL,
NULL,
&error);
g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_ONLY_PULLED);
g_assert_null (ref);
g_clear_error (&error);
res = flatpak_installation_remove_local_ref_sync (inst,
repo_name,
app,
NULL,
&error);
g_assert_no_error (error);
g_assert_true (res);
res = flatpak_installation_prune_local_repo (inst, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
}
static void
test_bad_remote_name (void)
{
g_autoptr(FlatpakInstallation) inst = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(FlatpakRemote) remote = NULL;
gboolean res;
inst = flatpak_installation_new_user (NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (inst);
empty_installation (inst);
remote = flatpak_remote_new ("3X \n bad");
flatpak_remote_set_url (remote, "not a url at all");
res = flatpak_installation_modify_remote (inst, remote, NULL, &error);
g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_INVALID_DATA);
g_assert_false (res);
}
/* Disable all remotes, and install an app from a repo that does not have the runtime.
* We expect an error.
*/
static void
test_transaction_no_runtime (void)
{
g_autoptr(FlatpakInstallation) inst = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(FlatpakTransaction) transaction = NULL;
gboolean res;
g_autofree char *s = NULL;
g_autoptr(GBytes) data = NULL;
FlatpakRemote *remote = NULL;
g_autoptr(GPtrArray) remotes = NULL;
int i;
inst = flatpak_installation_new_user (NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (inst);
empty_installation (inst);
remotes = flatpak_installation_list_remotes (inst, NULL, &error);
g_assert_no_error (error);
for (i = 0; i < remotes->len; i++)
{
remote = g_ptr_array_index (remotes, i);
flatpak_remote_set_disabled (remote, TRUE);
res = flatpak_installation_modify_remote (inst, remote, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
}
transaction = flatpak_transaction_new_for_installation (inst, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (transaction);
s = g_strconcat ("[Flatpak Ref]\n"
"Title=Test App\n"
"Name=org.test.Hello\n"
"Branch=master\n"
"Url=http://127.0.0.1:", httpd_port, "/test-without-runtime\n"
"IsRuntime=False\n"
"SuggestRemoteName=my-little-repo\n"
"RuntimeRepo=http://127.0.0.1:", httpd_port, "/test/test-repo.flatpakrepo\n",
NULL);
data = g_bytes_new (s, strlen (s));
res = flatpak_transaction_add_install_flatpakref (transaction, data, &error);
g_assert_no_error (error);
g_assert_true (res);
res = flatpak_transaction_run (transaction, NULL, &error);
g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_RUNTIME_NOT_FOUND);
g_assert_false (res);
g_clear_error (&error);
for (i = 0; i < remotes->len; i++)
{
remote = g_ptr_array_index (remotes, i);
flatpak_remote_set_disabled (remote, FALSE);
res = flatpak_installation_modify_remote (inst, remote, NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
}
}
static void
test_installation_no_interaction (void)
{
g_autoptr(FlatpakInstallation) inst = NULL;
g_autoptr(GError) error = NULL;
inst = flatpak_installation_new_user (NULL, &error);
g_assert_no_error (error);
g_assert_false (flatpak_installation_get_no_interaction (inst));
flatpak_installation_set_no_interaction (inst, TRUE);
g_assert_true (flatpak_installation_get_no_interaction (inst));
}
static void
test_installation_unused_refs (void)
{
g_autoptr(FlatpakInstallation) inst = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(GPtrArray) refs = NULL;
FlatpakInstalledRef *iref;
inst = flatpak_installation_new_user (NULL, &error);
g_assert_no_error (error);
empty_installation (inst);
iref = flatpak_installation_install (inst, repo_name, FLATPAK_REF_KIND_APP, "org.test.Hello", NULL, "master", NULL, NULL, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (iref);
g_clear_object (&iref);
refs = flatpak_installation_list_unused_refs (inst, NULL, NULL, &error);
g_assert_nonnull (refs);
g_assert_no_error (error);
g_assert_cmpint (refs->len, ==, 0);
}
int
main (int argc, char *argv[])
{
int res;
g_test_init (&argc, &argv, NULL);
g_test_add_func ("/library/version", test_library_version);
g_test_add_func ("/library/types", test_library_types);
g_test_add_func ("/library/user-installation", test_user_installation);
g_test_add_func ("/library/system-installation", test_system_installation);
g_test_add_func ("/library/multiple-system-installation", test_multiple_system_installations);
g_test_add_func ("/library/installation-config", test_installation_config);
g_test_add_func ("/library/languages-config", test_languages_config);
g_test_add_func ("/library/arches", test_arches);
g_test_add_func ("/library/ref", test_ref);
g_test_add_func ("/library/list-remotes", test_list_remotes);
g_test_add_func ("/library/remote-by-name", test_remote_by_name);
g_test_add_func ("/library/remote", test_remote);
g_test_add_func ("/library/remote-new", test_remote_new);
g_test_add_func ("/library/remote-new-from-file", test_remote_new_from_file);
g_test_add_func ("/library/list-remote-refs", test_list_remote_refs);
g_test_add_func ("/library/list-remote-related-refs", test_list_remote_related_refs);
g_test_add_func ("/library/list-refs", test_list_refs);
g_test_add_func ("/library/install-launch-uninstall", test_install_launch_uninstall);
g_test_add_func ("/library/list-refs-in-remote", test_list_refs_in_remotes);
g_test_add_func ("/library/list-updates", test_list_updates);
g_test_add_func ("/library/list-updates-offline", test_list_updates_offline);
g_test_add_func ("/library/transaction", test_misc_transaction);
g_test_add_func ("/library/transaction-install-uninstall", test_transaction_install_uninstall);
g_test_add_func ("/library/transaction-install-flatpakref", test_transaction_install_flatpakref);
g_test_add_func ("/library/transaction-flatpakref-remote-creation", test_transaction_flatpakref_remote_creation);
g_test_add_func ("/library/transaction-deps", test_transaction_deps);
g_test_add_func ("/library/transaction-install-local", test_transaction_install_local);
g_test_add_func ("/library/instance", test_instance);
g_test_add_func ("/library/update-subpaths", test_update_subpaths);
g_test_add_func ("/library/overrides", test_overrides);
g_test_add_func ("/library/bundle", test_bundle);
g_test_add_func ("/library/install-bundle", test_install_bundle);
g_test_add_func ("/library/install-flatpakref", test_install_flatpakref);
g_test_add_func ("/library/list-installed-related-refs", test_list_installed_related_refs);
g_test_add_func ("/library/update-related-refs", test_update_related_refs);
g_test_add_func ("/library/update-installed-ref-if-missing-runtime", test_update_installed_ref_if_missing_runtime);
g_test_add_func ("/library/no-deploy", test_no_deploy);
g_test_add_func ("/library/bad-remote-name", test_bad_remote_name);
g_test_add_func ("/library/transaction-no-runtime", test_transaction_no_runtime);
g_test_add_func ("/library/installation-no-interaction", test_installation_no_interaction);
g_test_add_func ("/library/installation-unused-refs", test_installation_unused_refs);
global_setup ();
res = g_test_run ();
global_teardown ();
return res;
}