Retrieve some missing test files from upstream git
authorSimon McVittie <smcv@debian.org>
Fri, 7 Oct 2016 22:14:40 +0000 (23:14 +0100)
committerSjoerd Simons <sjoerd@debian.org>
Thu, 3 Nov 2016 21:48:01 +0000 (21:48 +0000)
These were missing from "make dist".

Gbp-Pq: Topic dist
Gbp-Pq: Name Retrieve-some-missing-test-files-from-upstream-git.patch

tests/glib.supp [new file with mode: 0644]
tests/ostree.supp [new file with mode: 0644]
tests/test-core.js [new file with mode: 0644]
tests/test-corruption.sh [new file with mode: 0644]
tests/test-sizes.js [new file with mode: 0644]
tests/test-sysroot.js [new file with mode: 0644]

diff --git a/tests/glib.supp b/tests/glib.supp
new file mode 100644 (file)
index 0000000..7ac6ed8
--- /dev/null
@@ -0,0 +1,562 @@
+# This GLib suppressions file is known to be used at least by:
+#
+#  - rpm-software-management/libhif
+#
+# Please use the upstream verison in libhif for changes.
+{
+   gobject_init_1
+   Memcheck:Leak
+   ...
+   fun:gobject_init
+}
+{
+   g_type_register_static_1
+   Memcheck:Leak
+   ...
+   fun:g_type_register_static
+}
+{
+   g_type_register_dynamic
+   Memcheck:Leak
+   ...
+   fun:g_type_register_dynamic
+}
+{
+   g_type_register_fundamental
+   Memcheck:Leak
+   ...
+   fun:g_type_register_fundamental
+}
+{
+   g_type_init_with_debug_flags
+   Memcheck:Leak
+   ...
+   fun:g_type_init_with_debug_flags
+}
+{
+   g_type_class_ref_1
+   Memcheck:Leak
+   ...
+   fun:type_iface_vtable_base_init_Wm
+   ...
+   fun:g_type_class_ref
+}
+{
+   g_type_class_ref_2
+   Memcheck:Leak
+   ...
+   fun:type_class_init_Wm
+   ...
+   fun:g_type_class_ref
+}
+{
+   g_type_add_interface_static
+   Memcheck:Leak
+   ...
+   fun:g_type_add_interface_static
+}
+{
+   g_type_add_interface_dynamic
+   Memcheck:Leak
+   ...
+   fun:g_type_add_interface_dynamic
+}
+{
+   g_param_spec_internal
+   Memcheck:Leak
+   ...
+   fun:g_type_class_ref
+   fun:g_type_create_instance
+   fun:g_param_spec_internal
+}
+{
+   g_param_spec_enum
+   Memcheck:Leak
+   ...
+   fun:g_type_class_ref
+   fun:g_param_spec_enum
+}
+{
+   g_param_spec_flags
+   Memcheck:Leak
+   ...
+   fun:g_type_class_ref
+   fun:g_param_spec_flags
+}
+{
+   g_quark_from_static_string
+   Memcheck:Leak
+   ...
+   fun:g_quark_from_static_string
+}
+{
+   g_quark_from_string
+   Memcheck:Leak
+   ...
+   fun:g_quark_from_string
+}
+{
+   g_value_register_transform_func
+   Memcheck:Leak
+   ...
+   fun:g_value_register_transform_func
+}
+{
+   test_run_seed
+   Memcheck:Leak
+   ...
+   fun:g_rand_new_with_seed_array
+   fun:test_run_seed
+   ...
+   fun:g_test_run_suite
+}
+{
+   g_test_init
+   Memcheck:Leak
+   ...
+   fun:g_rand_new_with_seed_array
+   ...
+   fun:g_test_init
+}
+{
+   g_intern_static_string
+   Memcheck:Leak
+   ...
+   fun:g_intern_static_string
+}
+{
+   g_main_context_push_thread_default
+   Memcheck:Leak
+   ...
+   fun:g_queue_new
+   fun:g_main_context_push_thread_default
+}
+{
+   g_main_context_push_thread_default_inlined
+   Memcheck:Leak
+   ...
+   fun:g_slice_alloc0
+   fun:g_main_context_push_thread_default
+}
+{
+   g_dbus_error_register_error
+   Memcheck:Leak
+   ...
+   fun:g_dbus_error_register_error
+}
+{
+   g_param_spec_pool_insert
+   Memcheck:Leak
+   ...
+   fun:g_param_spec_pool_insert
+}
+{
+   g_main_context_default
+   Memcheck:Leak
+   ...
+   fun:g_main_context_default
+}
+{
+   g_main_context_check
+   Memcheck:Leak
+   ...
+   fun:g_ptr_array_add
+   fun:g_main_context_check
+}
+{
+   g_test_run_suite
+   Memcheck:Leak
+   ...
+   fun:g_slist_copy
+   fun:g_test_run_suite_internal
+   fun:g_test_run_suite
+}
+{
+   g_dbus_interface_info_cache_build
+   Memcheck:Leak
+   ...
+   fun:g_dbus_interface_info_cache_build
+}
+{
+   g_cancellable_push_current
+   Memcheck:Leak
+   ...
+   fun:thread_memory_from_self
+   ...
+   fun:g_cancellable_push_current
+}
+{
+   _g_io_module_get_default
+   Memcheck:Leak
+   ...
+   fun:g_io_module_new
+   fun:g_io_modules_scan_all_in_directory_with_scope
+   fun:_g_io_modules_ensure_loaded
+   fun:_g_io_module_get_default
+}
+{
+   g_io_scheduler_push_job
+   Memcheck:Leak
+   ...
+   fun:init_scheduler
+   fun:g_once_impl
+   fun:g_io_scheduler_push_job
+}
+{
+   g_io_scheduler_push_job_2
+   Memcheck:Leak
+   ...
+   fun:g_system_thread_new
+   ...
+   fun:g_io_scheduler_push_job
+}
+{
+   g_bus_get_sync__available_connections
+   Memcheck:Leak
+   ...
+   fun:g_hash_table_new
+   fun:initable_init
+   fun:g_initable_init
+   fun:g_bus_get_sync
+}
+{
+   g_socket_connection_factory_register_type
+   Memcheck:Leak
+   ...
+   fun:g_socket_connection_factory_register_type
+}
+{
+   g_test_add_vtable
+   Memcheck:Leak
+   ...
+   fun:g_test_add_vtable
+}
+{
+   g_mutex_lock
+   Memcheck:Leak
+   ...
+   fun:g_mutex_impl_new
+   fun:g_mutex_get_impl
+   fun:g_mutex_lock
+}
+{
+   g_thread_self
+   Memcheck:Leak
+   ...
+   fun:g_thread_self
+}
+{
+   g_rec_mutex_lock
+   Memcheck:Leak
+   ...
+   fun:g_rec_mutex_impl_new
+   fun:g_rec_mutex_get_impl
+   fun:g_rec_mutex_lock
+}
+{
+   test_case_run
+   Memcheck:Leak
+   ...
+   fun:g_malloc0
+   fun:test_case_run
+   ...
+   fun:g_test_run_suite
+}
+{
+   g_get_charset
+   Memcheck:Leak
+   ...
+   fun:g_get_charset
+}
+{
+   g_test_run_suite__timer_new
+   Memcheck:Leak
+   ...
+   fun:g_timer_new
+   fun:test_case_run
+   ...
+   fun:g_test_run_suite
+}
+{
+   g_test_run_suite__timer_new2
+   Memcheck:Leak
+   ...
+   fun:g_timer_new
+   fun:test_case_run_suite_internal
+   ...
+   fun:g_test_run_suite
+}
+{
+   g_test_run_suite__strconcat
+   Memcheck:Leak
+   ...
+   fun:g_strconcat
+   fun:test_case_run
+   ...
+   fun:g_test_run_suite
+   fun:g_test_run
+}
+{
+   g_type_interface_add_prerequisite
+   Memcheck:Leak
+   ...
+   fun:g_type_interface_add_prerequisite
+}
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   ...
+   fun:g_slist_copy
+   fun:g_test_run_suite_internal
+   ...
+   fun:g_test_run_suite
+}
+{
+   g_set_prgname
+   Memcheck:Leak
+   ...
+   fun:g_set_prgname
+}
+{
+   g_test_run_suite__strconcat_2
+   Memcheck:Leak
+   ...
+   fun:g_strconcat
+   fun:g_test_run_suite_internal
+}
+{
+   g_test_run_suite__strdup
+   Memcheck:Leak
+   ...
+   fun:g_strdup
+   fun:g_test_run_suite_internal
+}
+{
+   g_private_get
+   Memcheck:Leak
+   ...
+   fun:g_private_get
+}
+{
+   g_private_set
+   Memcheck:Leak
+   ...
+   fun:g_private_set
+}
+{
+   g_static_mutex_get_mutex_impl
+   Memcheck:Leak
+   ...
+   fun:g_static_mutex_get_mutex_impl
+}
+{
+   g_variant_type_info_unref
+   Memcheck:Leak
+   ...
+   fun:g_hash_table_remove
+   fun:g_variant_type_info_unref
+}
+{
+   g_rw_lock_reader_lock
+   Memcheck:Leak
+   ...
+   fun:g_rw_lock_impl_new
+   fun:g_rw_lock_get_impl
+   fun:g_rw_lock_reader_lock
+}
+{
+   g_child_watch_finalize__rt_sigaction
+   Memcheck:Param
+   rt_sigaction(act->sa_flags)
+   fun:__libc_sigaction
+   ...
+   fun:g_child_watch_finalize
+}
+{
+   g_dbus_worker_new
+   Memcheck:Leak
+   fun:calloc
+   ...
+   fun:_g_dbus_worker_new
+}
+{
+   gdbus_shared_thread_func
+   Memcheck:Leak
+   match-leak-kinds: definite
+   ...
+   fun:g_malloc
+   ...
+   fun:gdbus_shared_thread_func
+}
+{
+   g_task_start_task_thread
+   Memcheck:Leak
+   match-leak-kinds: definite
+   fun:malloc
+   fun:g_malloc
+   fun:g_slice_alloc
+   fun:g_slice_alloc0
+   ...
+   fun:g_thread_pool_push
+   fun:g_task_start_task_thread
+}
+{
+   g_task_to_pool
+   Memcheck:Leak
+   ...
+   fun:g_thread_pool_start_thread
+   ...
+   fun:g_task_run_in_thread
+}
+{
+   g_get_language_names
+   Memcheck:Leak
+   match-leak-kinds: definite
+   fun:calloc
+   fun:g_malloc0
+   fun:g_get_language_names
+}
+{
+   g_get_filename_charsets
+   Memcheck:Leak
+   match-leak-kinds: definite
+   ...
+   fun:g_get_filename_charsets
+   fun:g_filename_display_name
+}
+{
+   g_main_current_source
+   Memcheck:Leak
+   match-leak-kinds: definite
+   fun:malloc
+   fun:g_malloc
+   ...
+   fun:g_main_current_source
+   fun:g_task_return
+   fun:g_task_thread_pool_thread
+}
+{
+   g_once_init_enter
+   Memcheck:Leak
+   match-leak-kinds: definite
+   ...
+   fun:g_once_init_enter
+}
+{
+   g_child_watch_source_new
+   Memcheck:Leak
+   match-leak-kinds: definite
+   ...
+   fun:g_thread_new
+   ...
+   fun:g_child_watch_source_new
+}
+{
+   continue_writing_in_idle_cb
+   Memcheck:Leak
+   match-leak-kinds: definite
+   ...
+   fun:g_task_new
+   ...
+   fun:continue_writing_in_idle_cb
+   fun:g_main_context_dispatch
+}
+{
+   g_main_current_source
+   Memcheck:Leak
+   match-leak-kinds: definite
+   fun:malloc
+   ...
+   fun:g_main_current_source
+}
+{
+   g_thread_pool_push
+   Memcheck:Leak
+   match-leak-kinds: definite
+   fun:malloc
+   ...
+   fun:g_thread_pool_push
+}
+{
+   leak_test_dbus_dispose
+   Memcheck:Leak
+   match-leak-kinds: definite
+   fun:malloc
+   ...
+   fun:g_main_loop_run
+   fun:g_test_dbus_down
+}
+{
+   leak_test_dbus_down
+   Memcheck:Leak
+   match-leak-kinds: definite
+   fun:calloc
+   fun:g_malloc0
+   fun:g_main_loop_new
+   fun:g_test_dbus_down
+}
+{
+   leak_socket_client_connect
+   Memcheck:Leak
+   match-leak-kinds: definite
+   fun:malloc
+   fun:g_malloc
+   fun:g_slice_alloc
+   fun:g_slice_alloc0
+   fun:g_socket_client_connect_async
+   fun:g_socket_client_connect_to_uri_async
+}
+{
+   leak_signal_handlers_disconnect_matched
+   Memcheck:Leak
+   match-leak-kinds: definite
+   fun:calloc
+   fun:g_malloc0
+   ...
+   fun:g_slice_alloc
+   ...
+   fun:g_signal_handlers_disconnect_matched
+}
+{
+   g_tls_connection_gnutls_init_priorities
+   Memcheck:Leak
+   match-leak-kinds: definite
+   fun:malloc
+   fun:g_malloc
+   fun:g_strdup
+   fun:g_tls_connection_gnutls_init_priorities
+}
+{
+   g_tls_connection_gnutls_heisenbug_likely_same_as_above
+   Memcheck:Leak
+   match-leak-kinds: definite
+   fun:malloc
+   fun:g_malloc
+   fun:g_strdup
+   ...
+   fun:g_tls_client_connection_new
+}
+{
+   g_unix_signal_add_full
+   Memcheck:Leak
+   match-leak-kinds: definite
+   fun:malloc
+   fun:g_malloc
+   ...
+   fun:g_thread_new
+   ...
+   fun:g_unix_signal_add_full
+}
+{
+   glib_worker_1
+   Memcheck:Leak
+   ...
+   fun:glib_worker_main
+}
+{
+   glib_worker_2
+   Memcheck:Leak
+   ...
+   fun:g_thread_new
+   fun:g_get_worker_context
+}
diff --git a/tests/ostree.supp b/tests/ostree.supp
new file mode 100644 (file)
index 0000000..b81ea51
--- /dev/null
@@ -0,0 +1 @@
+# Use this to suppress "possibly lost" for global statics
diff --git a/tests/test-core.js b/tests/test-core.js
new file mode 100644 (file)
index 0000000..e9ace6e
--- /dev/null
@@ -0,0 +1,55 @@
+#!/usr/bin/env gjs
+//
+// Copyright (C) 2013 Colin Walters <walters@verbum.org>
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+const Gio = imports.gi.Gio;
+const OSTree = imports.gi.OSTree;
+
+function assertEquals(a, b) {
+    if (a != b)
+       throw new Error("assertion failed " + JSON.stringify(a) + " == " + JSON.stringify(b));
+}
+
+let testDataDir = Gio.File.new_for_path('test-data');
+testDataDir.make_directory(null);
+testDataDir.get_child('some-file').replace_contents("hello world!", null, false, 0, null);
+
+let repoPath = Gio.File.new_for_path('repo');
+let repo = OSTree.Repo.new(repoPath);
+repo.create(OSTree.RepoMode.ARCHIVE_Z2, null);
+
+repo.open(null);
+
+assertEquals(repo.get_mode(), OSTree.RepoMode.ARCHIVE_Z2);
+
+repo.prepare_transaction(null);
+
+let mtree = OSTree.MutableTree.new();
+repo.write_directory_to_mtree(testDataDir, mtree, null, null);
+let [,dirTree] = repo.write_mtree(mtree, null);
+let [,commit] = repo.write_commit(null, 'Some subject', 'Some body', null, dirTree, null);
+print("commit => " + commit);
+
+repo.commit_transaction(null, null);
+
+let [,root,checksum] = repo.read_commit(commit, null);
+let child = root.get_child('some-file');
+let info = child.query_info("standard::name,standard::type,standard::size", 0, null);
+assertEquals(info.get_size(), 12);
+
+print("test-core complete");
diff --git a/tests/test-corruption.sh b/tests/test-corruption.sh
new file mode 100644 (file)
index 0000000..ef0e94e
--- /dev/null
@@ -0,0 +1,43 @@
+#!/bin/bash
+#
+# Copyright (C) 2011 Colin Walters <walters@verbum.org>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+set -euo pipefail
+
+echo "1..2"
+
+. $(dirname $0)/libtest.sh
+
+setup_test_repository "bare"
+$OSTREE checkout test2 checkout-test2
+cd checkout-test2
+chmod o+x firstfile
+$OSTREE fsck -q && (echo 1>&2 "fsck unexpectedly succeeded"; exit 1)
+chmod o-x firstfile
+$OSTREE fsck -q
+
+echo "ok chmod"
+
+cd ${test_tmpdir}
+rm checkout-test2 -rf
+$OSTREE checkout test2 checkout-test2
+cd checkout-test2
+chmod o+x firstfile
+$OSTREE fsck -q --delete && (echo 1>&2 "fsck unexpectedly succeeded"; exit 1)
+
+echo "ok chmod"
diff --git a/tests/test-sizes.js b/tests/test-sizes.js
new file mode 100644 (file)
index 0000000..5cf765f
--- /dev/null
@@ -0,0 +1,82 @@
+#!/usr/bin/env gjs
+//
+// Copyright (C) 2013 Colin Walters <walters@verbum.org>
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+const GLib = imports.gi.GLib;
+const Gio = imports.gi.Gio;
+const OSTree = imports.gi.OSTree;
+
+function assertEquals(a, b) {
+    if (a != b)
+       throw new Error("assertion failed " + JSON.stringify(a) + " == " + JSON.stringify(b));
+}
+
+let testDataDir = Gio.File.new_for_path('test-data');
+testDataDir.make_directory(null);
+testDataDir.get_child('some-file').replace_contents("hello world!", null, false, 0, null);
+testDataDir.get_child('another-file').replace_contents("hello world again!", null, false, 0, null);
+
+let repoPath = Gio.File.new_for_path('repo');
+let repo = OSTree.Repo.new(repoPath);
+repo.create(OSTree.RepoMode.ARCHIVE_Z2, null);
+
+repo.open(null);
+
+let commitModifier = OSTree.RepoCommitModifier.new(OSTree.RepoCommitModifierFlags.GENERATE_SIZES, null);
+
+assertEquals(repo.get_mode(), OSTree.RepoMode.ARCHIVE_Z2);
+
+repo.prepare_transaction(null);
+
+let mtree = OSTree.MutableTree.new();
+repo.write_directory_to_mtree(testDataDir, mtree, commitModifier, null);
+let [,dirTree] = repo.write_mtree(mtree, null);
+let [,commit] = repo.write_commit(null, 'Some subject', 'Some body', null, dirTree, null);
+print("commit => " + commit);
+
+repo.commit_transaction(null, null);
+
+// Test the sizes metadata
+let [,commitVariant] = repo.load_variant(OSTree.ObjectType.COMMIT, commit);
+let metadata = commitVariant.get_child_value(0);
+let sizes = metadata.lookup_value('ostree.sizes', GLib.VariantType.new('aay'));
+let nSizes = sizes.n_children();
+assertEquals(nSizes, 2);
+let expectedUncompressedSizes = [12, 18];
+let foundExpectedUncompressedSizes = 0;
+for (let i = 0; i < nSizes; i++) {
+    let sizeEntry = sizes.get_child_value(i).deep_unpack();
+    assertEquals(sizeEntry.length, 34);
+    let compressedSize = sizeEntry[32];
+    let uncompressedSize = sizeEntry[33];
+    print("compressed = " + compressedSize);
+    print("uncompressed = " + uncompressedSize);
+    for (let j = 0; j < expectedUncompressedSizes.length; j++) {
+       let expected = expectedUncompressedSizes[j];
+       if (expected == uncompressedSize) {
+           print("Matched expected uncompressed size " + expected);
+           expectedUncompressedSizes.splice(j, 1);
+           break;
+       }
+    }
+}
+if (expectedUncompressedSizes.length > 0) {
+    throw new Error("Failed to match expectedUncompressedSizes: " + JSON.stringify(expectedUncompressedSizes));
+}
+
+print("test-sizes complete");
diff --git a/tests/test-sysroot.js b/tests/test-sysroot.js
new file mode 100644 (file)
index 0000000..7e8fcf7
--- /dev/null
@@ -0,0 +1,147 @@
+#!/usr/bin/env gjs
+//
+// Copyright (C) 2013 Colin Walters <walters@verbum.org>
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+const GLib = imports.gi.GLib;
+const Gio = imports.gi.Gio;
+const OSTree = imports.gi.OSTree;
+
+function assertEquals(a, b) {
+    if (a != b)
+       throw new Error("assertion failed " + JSON.stringify(a) + " == " + JSON.stringify(b));
+}
+
+function assertNotEquals(a, b) {
+    if (a == b)
+       throw new Error("assertion failed " + JSON.stringify(a) + " != " + JSON.stringify(b));
+}
+
+function libtestExec(shellCode) {
+    let testdatadir = GLib.getenv("G_TEST_SRCDIR");
+    let libtestPath = GLib.build_filenamev([testdatadir, 'libtest.sh'])
+    let proc = Gio.Subprocess.new(['bash', '-c', 'set -xeuo pipefail; . ' + GLib.shell_quote(libtestPath) + '; ' + shellCode], 0);
+    proc.wait_check(null);
+}
+
+libtestExec('setup_os_repository archive-z2 syslinux');
+
+let upstreamRepo = OSTree.Repo.new(Gio.File.new_for_path('testos-repo'));
+upstreamRepo.open(null);
+
+let runtimeRef = 'testos/buildmaster/x86_64-runtime';
+let [,rev] = upstreamRepo.resolve_rev(runtimeRef, false);
+
+print("testos => " + rev);
+
+//// TEST: We should have no deployments
+
+let sysroot = OSTree.Sysroot.new(Gio.File.new_for_path('sysroot'));
+sysroot.load(null);
+let deployments = sysroot.get_deployments();
+assertEquals(deployments.length, 0);
+
+//// Add the remote, and do a pull
+
+let [,sysrootRepo] = sysroot.get_repo(null);
+sysrootRepo.remote_add('testos', 'file://' + upstreamRepo.get_path().get_path(),
+                      GLib.Variant.new('a{sv}', {'gpg-verify': GLib.Variant.new('b', false),
+                                                 'branches': GLib.Variant.new('as', [runtimeRef])}), null);
+sysrootRepo.pull('testos', null, 0, null, null);
+
+//// TEST: We can deploy one tree
+
+let mergeDeployment = sysroot.get_merge_deployment('testos');
+
+let origin = sysroot.origin_new_from_refspec(runtimeRef);
+let [,deployment] = sysroot.deploy_tree('testos', rev, origin,
+                                       mergeDeployment, null,
+                                       null);
+let newDeployments = deployments;
+deployments = null;
+newDeployments.unshift(deployment);
+sysroot.write_deployments(newDeployments, null);
+deployments = sysroot.get_deployments();
+assertEquals(deployments.length, newDeployments.length);
+assertEquals(deployments[0].get_csum(), deployment.get_csum());
+
+let deploymentPath = sysroot.get_deployment_directory(deployment);
+assertEquals(deploymentPath.query_exists(null), true);
+
+print("OK one deployment");
+
+/// TEST: We can delete the deployment, going back to empty
+sysroot.write_deployments([], null);
+
+print("OK empty deployments");
+
+assertEquals(deploymentPath.query_exists(null), false);
+
+//// Ok, redeploy, then add a new revision upstream and pull it
+
+let [,deployment] = sysroot.deploy_tree('testos', rev, origin,
+                                       mergeDeployment, null,
+                                       null);
+newDeployments = deployments;
+deployments = null;
+newDeployments.unshift(deployment);
+print(JSON.stringify(newDeployments));
+sysroot.write_deployments(newDeployments, null);
+
+libtestExec('os_repository_new_commit');
+
+sysrootRepo.pull('testos', null, 0, null, null);
+
+let [,newRev] = upstreamRepo.resolve_rev(runtimeRef, false);
+
+print("testos => " + newRev);
+assertNotEquals(rev, newRev);
+
+mergeDeployment = sysroot.get_merge_deployment('testos');
+assertEquals(mergeDeployment.get_csum(), deployment.get_csum());
+let [,newDeployment] = sysroot.deploy_tree('testos', newRev, origin,
+                                          mergeDeployment, null,
+                                          null);
+newDeployments = [newDeployment, mergeDeployment];
+assertNotEquals(mergeDeployment.get_bootcsum(), newDeployment.get_bootcsum());
+assertNotEquals(mergeDeployment.get_csum(), newDeployment.get_csum());
+sysroot.write_deployments(newDeployments, null);
+deployments = sysroot.get_deployments();
+assertEquals(deployments.length, 2);
+assertEquals(deploymentPath.query_exists(null), true);
+let newDeploymentPath = sysroot.get_deployment_directory(newDeployment);
+assertEquals(newDeploymentPath.query_exists(null), true);
+
+print("OK two deployments");
+
+libtestExec('os_repository_new_commit 0 1');
+
+sysrootRepo.pull('testos', null, 0, null, null);
+
+let [,thirdRev] = sysrootRepo.resolve_rev(runtimeRef, false);
+assertNotEquals(newRev, thirdRev);
+
+mergeDeployment = sysroot.get_merge_deployment('testos');
+let [,thirdDeployment] = sysroot.deploy_tree('testos', thirdRev, origin,
+                                            mergeDeployment, null,
+                                            null);
+assertEquals(mergeDeployment.get_bootcsum(), thirdDeployment.get_bootcsum());
+assertNotEquals(mergeDeployment.get_csum(), thirdDeployment.get_csum());
+newDeployments = [deployment, newDeployment, thirdDeployment];
+sysroot.write_deployments(newDeployments, null);
+deployments = sysroot.get_deployments();
+assertEquals(deployments.length, 3);