New upstream version 2017.8
This commit is contained in:
commit
b6c0af922c
158 files changed
+12692
-2420
No files matched your search
+7
-3
@@ -342,8 +342,11 @@ cd ${test_tmpdir}
|
||||
cat > test-statoverride.txt <<EOF
|
||||
+1048 /a/nested/2
|
||||
2048 /a/nested/3
|
||||
=384 /a/readable-only
|
||||
EOF
|
||||
cd ${test_tmpdir}/checkout-test2-4
|
||||
echo readable only > a/readable-only
|
||||
chmod 664 a/readable-only
|
||||
$OSTREE commit ${COMMIT_ARGS} -b test2-override -s "with statoverride" --statoverride=../test-statoverride.txt
|
||||
cd ${test_tmpdir}
|
||||
$OSTREE checkout test2-override checkout-test2-override
|
||||
@@ -354,6 +357,7 @@ else
|
||||
test '!' -g checkout-test2-override/a/nested/2
|
||||
test '!' -u checkout-test2-override/a/nested/3
|
||||
fi
|
||||
assert_file_has_mode checkout-test2-override/a/readable-only 600
|
||||
echo "ok commit statoverride"
|
||||
|
||||
cd ${test_tmpdir}
|
||||
@@ -492,7 +496,7 @@ echo "ok pull-local with --remote arg"
|
||||
cd ${test_tmpdir}
|
||||
${CMD_PREFIX} ostree --repo=repo3 prune
|
||||
find repo3/objects -name '*.commit' > objlist-before-prune
|
||||
rm repo3/refs/heads/* repo3/refs/remotes/* -rf
|
||||
rm repo3/refs/heads/* repo3/refs/mirrors/* repo3/refs/remotes/* -rf
|
||||
${CMD_PREFIX} ostree --repo=repo3 prune --refs-only
|
||||
find repo3/objects -name '*.commit' > objlist-after-prune
|
||||
if cmp -s objlist-before-prune objlist-after-prune; then
|
||||
@@ -512,7 +516,7 @@ find repo3/objects -name '*.filez' > file-objects
|
||||
if test -s file-objects; then
|
||||
assert_not_reached "prune didn't delete all objects"
|
||||
fi
|
||||
echo "ok prune in archive-z2 deleted everything"
|
||||
echo "ok prune in archive deleted everything"
|
||||
|
||||
cd ${test_tmpdir}
|
||||
rm -rf test2-checkout
|
||||
@@ -730,7 +734,7 @@ $OSTREE commit ${COMMIT_ARGS} -b test2 -s "Unfsynced commit" --fsync=false
|
||||
if test "$(id -u)" != "0"; then
|
||||
cd ${test_tmpdir}
|
||||
rm -f expected-fail error-message
|
||||
$OSTREE init --mode=archive-z2 --repo=repo-noperm
|
||||
$OSTREE init --mode=archive --repo=repo-noperm
|
||||
chmod -w repo-noperm/objects
|
||||
$OSTREE --repo=repo-noperm pull-local repo 2> error-message || touch expected-fail
|
||||
chmod +w repo-noperm/objects
|
||||
|
||||
+17
-6
@@ -117,15 +117,14 @@ else
|
||||
fi
|
||||
|
||||
files_are_hardlinked() {
|
||||
f1=$(stat -c %i $1)
|
||||
f2=$(stat -c %i $2)
|
||||
[ "$f1" == "$f2" ]
|
||||
inode1=$(stat -c %i $1)
|
||||
inode2=$(stat -c %i $2)
|
||||
test -n "${inode1}" && test -n "${inode2}"
|
||||
[ "${inode1}" == "${inode2}" ]
|
||||
}
|
||||
|
||||
assert_files_hardlinked() {
|
||||
f1=$(stat -c %i $1)
|
||||
f2=$(stat -c %i $2)
|
||||
if ! files_are_hardlinked "$f1" "$f2"; then
|
||||
if ! files_are_hardlinked "$1" "$2"; then
|
||||
fatal "Files '$1' and '$2' are not hardlinked"
|
||||
fi
|
||||
}
|
||||
@@ -537,3 +536,15 @@ ostree_file_path_to_object_path() {
|
||||
relpath=$(ostree_file_path_to_relative_object_path $repo $ref $path)
|
||||
echo ${repo}/${relpath}
|
||||
}
|
||||
|
||||
# Assert ref $2 in repo $1 has checksum $3.
|
||||
assert_ref () {
|
||||
assert_streq $(${CMD_PREFIX} ostree rev-parse --repo=$1 $2) $3
|
||||
}
|
||||
|
||||
# Assert no ref named $2 is present in repo $1.
|
||||
assert_not_ref () {
|
||||
if ${CMD_PREFIX} ostree rev-parse --repo=$1 $2 2>/dev/null; then
|
||||
fatal "rev-parse $2 unexpectedly succeeded!"
|
||||
fi
|
||||
}
|
||||
+30
-8
@@ -35,12 +35,14 @@ function verify_initial_contents() {
|
||||
assert_file_has_content baz/cow '^moo$'
|
||||
}
|
||||
|
||||
echo "1..25"
|
||||
echo "1..26"
|
||||
|
||||
# Try both syntaxes
|
||||
repo_init --no-gpg-verify
|
||||
${CMD_PREFIX} ostree --repo=repo pull origin main
|
||||
${CMD_PREFIX} ostree --repo=repo pull origin:main
|
||||
${CMD_PREFIX} ostree --repo=repo pull origin main >out.txt
|
||||
assert_file_has_content out.txt "[1-9][0-9]* metadata, [1-9][0-9]* content objects fetched"
|
||||
${CMD_PREFIX} ostree --repo=repo pull origin:main > out.txt
|
||||
assert_not_file_has_content out.txt "content objects fetched"
|
||||
${CMD_PREFIX} ostree --repo=repo fsck
|
||||
echo "ok pull"
|
||||
|
||||
@@ -50,7 +52,7 @@ echo "ok pull contents"
|
||||
|
||||
cd ${test_tmpdir}
|
||||
mkdir mirrorrepo
|
||||
ostree_repo_init mirrorrepo --mode=archive-z2
|
||||
ostree_repo_init mirrorrepo --mode=archive
|
||||
${CMD_PREFIX} ostree --repo=mirrorrepo remote add --set=gpg-verify=false origin $(cat httpd-address)/ostree/gnomerepo
|
||||
${CMD_PREFIX} ostree --repo=mirrorrepo pull --mirror origin main
|
||||
${CMD_PREFIX} ostree --repo=mirrorrepo fsck
|
||||
@@ -63,7 +65,7 @@ ${CMD_PREFIX} ostree --repo=ostree-srv/gnomerepo commit -b otherbranch --tree=di
|
||||
${CMD_PREFIX} ostree --repo=ostree-srv/gnomerepo summary -u
|
||||
rm mirrorrepo -rf
|
||||
# All refs
|
||||
ostree_repo_init mirrorrepo --mode=archive-z2
|
||||
ostree_repo_init mirrorrepo --mode=archive
|
||||
${CMD_PREFIX} ostree --repo=mirrorrepo remote add --set=gpg-verify=false origin $(cat httpd-address)/ostree/gnomerepo
|
||||
${CMD_PREFIX} ostree --repo=mirrorrepo pull --mirror origin
|
||||
${CMD_PREFIX} ostree --repo=mirrorrepo fsck
|
||||
@@ -73,7 +75,7 @@ done
|
||||
echo "ok pull mirror (all refs)"
|
||||
|
||||
rm mirrorrepo -rf
|
||||
ostree_repo_init mirrorrepo --mode=archive-z2
|
||||
ostree_repo_init mirrorrepo --mode=archive
|
||||
${CMD_PREFIX} ostree --repo=mirrorrepo remote add --set=gpg-verify=false origin $(cat httpd-address)/ostree/gnomerepo
|
||||
# Generate a summary in the mirror
|
||||
${CMD_PREFIX} ostree --repo=mirrorrepo summary -u
|
||||
@@ -152,13 +154,33 @@ echo "ok pull commit metadata only (should not apply deltas)"
|
||||
|
||||
cd ${test_tmpdir}
|
||||
mkdir mirrorrepo-local
|
||||
ostree_repo_init mirrorrepo-local --mode=archive-z2
|
||||
ostree_repo_init mirrorrepo-local --mode=archive
|
||||
${CMD_PREFIX} ostree --repo=mirrorrepo-local remote add --set=gpg-verify=false origin file://$(pwd)/ostree-srv/gnomerepo
|
||||
${CMD_PREFIX} ostree --repo=mirrorrepo-local pull --mirror origin main
|
||||
${CMD_PREFIX} ostree --repo=mirrorrepo-local fsck
|
||||
$OSTREE show main >/dev/null
|
||||
echo "ok pull local mirror"
|
||||
|
||||
cd ${test_tmpdir}
|
||||
# This is more of a known issue; test that we give a clean error right now
|
||||
rm otherrepo -rf
|
||||
ostree_repo_init otherrepo --mode=archive
|
||||
rm checkout-origin-main -rf
|
||||
${CMD_PREFIX} ostree --repo=ostree-srv/gnomerepo checkout main checkout-origin-main
|
||||
${CMD_PREFIX} ostree --repo=otherrepo commit -b localbranch --tree=dir=checkout-origin-main
|
||||
${CMD_PREFIX} ostree --repo=otherrepo remote add --set=gpg-verify=false origin file://$(pwd)/ostree-srv/gnomerepo
|
||||
${CMD_PREFIX} ostree --repo=otherrepo pull origin main
|
||||
rm mirrorrepo-local -rf
|
||||
ostree_repo_init mirrorrepo-local --mode=archive
|
||||
if ${CMD_PREFIX} ostree --repo=mirrorrepo-local pull-local otherrepo 2>err.txt; then
|
||||
fatal "pull with mixed refs succeeded?"
|
||||
fi
|
||||
assert_file_has_content err.txt "error: Invalid ref name origin:main"
|
||||
${CMD_PREFIX} ostree --repo=mirrorrepo-local pull-local otherrepo localbranch
|
||||
${CMD_PREFIX} ostree --repo=mirrorrepo-local rev-parse localbranch
|
||||
${CMD_PREFIX} ostree --repo=mirrorrepo-local fsck
|
||||
echo "ok pull-local mirror errors with mixed refs"
|
||||
|
||||
cd ${test_tmpdir}
|
||||
${CMD_PREFIX} ostree --repo=ostree-srv/gnomerepo commit -b main -s "Metadata string" --add-detached-metadata-string=SIGNATURE=HANCOCK --tree=ref=main
|
||||
${CMD_PREFIX} ostree --repo=ostree-srv/gnomerepo summary -u
|
||||
@@ -170,7 +192,7 @@ echo "ok pull detached metadata"
|
||||
|
||||
cd ${test_tmpdir}
|
||||
mkdir parentpullrepo
|
||||
ostree_repo_init parentpullrepo --mode=archive-z2
|
||||
ostree_repo_init parentpullrepo --mode=archive
|
||||
${CMD_PREFIX} ostree --repo=parentpullrepo remote add --set=gpg-verify=false origin file://$(pwd)/ostree-srv/gnomerepo
|
||||
parent_rev=$(ostree --repo=ostree-srv/gnomerepo rev-parse main^)
|
||||
rev=$(ostree --repo=ostree-srv/gnomerepo rev-parse main)
|
||||
|
||||
@@ -185,6 +185,25 @@ static gboolean hi_content_stream_new (GInputStream **out_stream,
|
||||
return ostree_raw_file_to_content_stream ((GInputStream*)hi_memstream, finfo, NULL, out_stream, out_length, NULL, error);
|
||||
}
|
||||
|
||||
static void
|
||||
test_validate_remotename (void)
|
||||
{
|
||||
const char *valid[] = {"foo", "hello-world"};
|
||||
const char *invalid[] = {"foo/bar", ""};
|
||||
for (guint i = 0; i < G_N_ELEMENTS(valid); i++)
|
||||
{
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_assert (ostree_validate_remote_name (valid[i], &error));
|
||||
g_assert_no_error (error);
|
||||
}
|
||||
for (guint i = 0; i < G_N_ELEMENTS(invalid); i++)
|
||||
{
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_assert (!ostree_validate_remote_name (invalid[i], &error));
|
||||
g_assert (error != NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
test_object_writes (gconstpointer data)
|
||||
{
|
||||
@@ -232,6 +251,7 @@ int main (int argc, char **argv)
|
||||
g_test_add_data_func ("/repo-not-system", repo, test_repo_is_not_system);
|
||||
g_test_add_data_func ("/raw-file-to-archive-z2-stream", repo, test_raw_file_to_archive_z2_stream);
|
||||
g_test_add_data_func ("/objectwrites", repo, test_object_writes);
|
||||
g_test_add_func ("/remotename", test_validate_remotename);
|
||||
|
||||
return g_test_run();
|
||||
out:
|
||||
|
||||
@@ -25,7 +25,7 @@ skip_without_user_xattrs
|
||||
|
||||
setup_test_repository "bare-user"
|
||||
|
||||
extra_basic_tests=3
|
||||
extra_basic_tests=4
|
||||
. $(dirname $0)/basic-test.sh
|
||||
|
||||
# Reset things so we don't inherit a lot of state from earlier tests
|
||||
@@ -64,3 +64,16 @@ $OSTREE checkout -U -H test2-unwritable test2-checkout
|
||||
cd test2-checkout
|
||||
assert_file_has_mode unwritable 400
|
||||
echo "ok bare-user unwritable"
|
||||
|
||||
rm test2-checkout -rf
|
||||
$OSTREE checkout -U -H test2 test2-checkout
|
||||
cat > statoverride.txt <<EOF
|
||||
=0 /unreadable
|
||||
EOF
|
||||
touch test2-checkout/unreadable
|
||||
$OSTREE commit -b test2-unreadable --statoverride=statoverride.txt --tree=dir=test2-checkout
|
||||
$OSTREE fsck
|
||||
rm test2-checkout -rf
|
||||
$OSTREE checkout -U -H test2-unreadable test2-checkout
|
||||
assert_file_has_mode test2-checkout/unreadable 400
|
||||
echo "ok bare-user handled unreadable file"
|
||||
@@ -0,0 +1,154 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||||
*
|
||||
* Copyright © 2017 Endless Mobile, Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Authors:
|
||||
* - Philip Withnall <withnall@endlessm.com>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include <glib.h>
|
||||
|
||||
#include "ostree-bloom-private.h"
|
||||
|
||||
/* Test the two different constructors work at a basic level. */
|
||||
static void
|
||||
test_bloom_init (void)
|
||||
{
|
||||
g_autoptr(OstreeBloom) bloom = NULL;
|
||||
g_autoptr(GBytes) bytes = NULL;
|
||||
|
||||
bloom = ostree_bloom_new (1, 1, ostree_str_bloom_hash);
|
||||
g_assert_cmpuint (ostree_bloom_get_size (bloom), ==, 1);
|
||||
g_assert_cmpuint (ostree_bloom_get_k (bloom), ==, 1);
|
||||
g_assert (ostree_bloom_get_hash_func (bloom) == ostree_str_bloom_hash);
|
||||
g_clear_pointer (&bloom, ostree_bloom_unref);
|
||||
|
||||
bytes = g_bytes_new_take (g_malloc0 (4), 4);
|
||||
bloom = ostree_bloom_new_from_bytes (bytes, 1, ostree_str_bloom_hash);
|
||||
g_assert_cmpuint (ostree_bloom_get_size (bloom), ==, 4);
|
||||
g_assert_cmpuint (ostree_bloom_get_k (bloom), ==, 1);
|
||||
g_assert (ostree_bloom_get_hash_func (bloom) == ostree_str_bloom_hash);
|
||||
g_clear_pointer (&bloom, ostree_bloom_unref);
|
||||
}
|
||||
|
||||
/* Test that building a bloom filter, marshalling it through GBytes, and loading
|
||||
* it again, gives the same element membership. */
|
||||
static void
|
||||
test_bloom_construction (void)
|
||||
{
|
||||
g_autoptr(OstreeBloom) bloom = NULL;
|
||||
g_autoptr(OstreeBloom) immutable_bloom = NULL;
|
||||
g_autoptr(GBytes) bytes = NULL;
|
||||
gsize i;
|
||||
const gchar *members[] =
|
||||
{
|
||||
"hello", "there", "these", "are", "test", "strings"
|
||||
};
|
||||
const gchar *non_members[] =
|
||||
{
|
||||
"not", "an", "element"
|
||||
};
|
||||
const gsize n_bytes = 256;
|
||||
const guint8 k = 8;
|
||||
const OstreeBloomHashFunc hash = ostree_str_bloom_hash;
|
||||
|
||||
/* Build a bloom filter. */
|
||||
bloom = ostree_bloom_new (n_bytes, k, hash);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (members); i++)
|
||||
ostree_bloom_add_element (bloom, members[i]);
|
||||
|
||||
bytes = ostree_bloom_seal (bloom);
|
||||
|
||||
/* Read it back from the GBytes. */
|
||||
immutable_bloom = ostree_bloom_new_from_bytes (bytes, k, hash);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (members); i++)
|
||||
g_assert_true (ostree_bloom_maybe_contains (bloom, members[i]));
|
||||
|
||||
/* This should never fail in future, as we guarantee the hash function will
|
||||
* never change. But given the definition of a bloom filter, it would also
|
||||
* be valid for these calls to return %TRUE. */
|
||||
for (i = 0; i < G_N_ELEMENTS (non_members); i++)
|
||||
g_assert_false (ostree_bloom_maybe_contains (bloom, non_members[i]));
|
||||
}
|
||||
|
||||
/* Test that an empty bloom filter definitely contains no elements. */
|
||||
static void
|
||||
test_bloom_empty (void)
|
||||
{
|
||||
g_autoptr(OstreeBloom) bloom = NULL;
|
||||
const gsize n_bytes = 256;
|
||||
const guint8 k = 8;
|
||||
const OstreeBloomHashFunc hash = ostree_str_bloom_hash;
|
||||
|
||||
/* Build an empty bloom filter. */
|
||||
bloom = ostree_bloom_new (n_bytes, k, hash);
|
||||
|
||||
g_assert_false (ostree_bloom_maybe_contains (bloom, "hello"));
|
||||
g_assert_false (ostree_bloom_maybe_contains (bloom, "there"));
|
||||
}
|
||||
|
||||
/* Build a bloom filter, and check the membership of the members as they are
|
||||
* added. */
|
||||
static void
|
||||
test_bloom_membership_during_construction (void)
|
||||
{
|
||||
g_autoptr(OstreeBloom) bloom = NULL;
|
||||
gsize i, j;
|
||||
const gchar *members[] =
|
||||
{
|
||||
"hello", "there", "these", "are", "test", "strings"
|
||||
};
|
||||
const gsize n_bytes = 256;
|
||||
const guint8 k = 8;
|
||||
const OstreeBloomHashFunc hash = ostree_str_bloom_hash;
|
||||
|
||||
/* These membership checks should never fail in future, as we guarantee
|
||||
* the hash function will never change. But given the definition of a bloom
|
||||
* filter, it would also be valid for these checks to fail. */
|
||||
bloom = ostree_bloom_new (n_bytes, k, hash);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (members); i++)
|
||||
{
|
||||
ostree_bloom_add_element (bloom, members[i]);
|
||||
|
||||
for (j = 0; j < G_N_ELEMENTS (members); j++)
|
||||
{
|
||||
if (j <= i)
|
||||
g_assert_true (ostree_bloom_maybe_contains (bloom, members[j]));
|
||||
else
|
||||
g_assert_false (ostree_bloom_maybe_contains (bloom, members[j]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
|
||||
g_test_add_func ("/bloom/init", test_bloom_init);
|
||||
g_test_add_func ("/bloom/construction", test_bloom_construction);
|
||||
g_test_add_func ("/bloom/empty", test_bloom_empty);
|
||||
g_test_add_func ("/bloom/membership-during-construction", test_bloom_membership_during_construction);
|
||||
|
||||
return g_test_run();
|
||||
}
|
||||
@@ -84,13 +84,13 @@ if ${CMD_PREFIX} ostree --repo=repo6 pull-local --remote=origin --gpg-verify-sum
|
||||
assert_not_reached "GPG summary verification with no summary unexpectedly succeeded"
|
||||
fi
|
||||
|
||||
${OSTREE} summary -u update
|
||||
${OSTREE} summary --update
|
||||
|
||||
if ${CMD_PREFIX} ostree --repo=repo6 pull-local --remote=origin --gpg-verify-summary repo test2 2>&1; then
|
||||
assert_not_reached "GPG summary verification with signed no summary unexpectedly succeeded"
|
||||
fi
|
||||
|
||||
${OSTREE} summary -u update --gpg-sign=${TEST_GPG_KEYID_1} --gpg-homedir=${TEST_GPG_KEYHOME}
|
||||
${OSTREE} summary --update --gpg-sign=${TEST_GPG_KEYID_1} --gpg-homedir=${TEST_GPG_KEYHOME}
|
||||
|
||||
${CMD_PREFIX} ostree --repo=repo6 pull-local --remote=origin --gpg-verify-summary repo test2 2>&1
|
||||
|
||||
|
||||
@@ -0,0 +1,400 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||||
*
|
||||
* Copyright © 2017 Endless Mobile, Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Authors:
|
||||
* - Philip Withnall <withnall@endlessm.com>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
#include <libglnx.h>
|
||||
|
||||
#include "test-mock-gio.h"
|
||||
|
||||
/**
|
||||
* SECTION:mock-gio
|
||||
* @title: Mock GIO volume interfaces
|
||||
* @short_description: Mock implementations of GIO volume, mount and drive
|
||||
* interfaces
|
||||
* @stability: Unstable
|
||||
* @include: tests/test-mock-gio.h
|
||||
*
|
||||
* A set of classes implementing GIO interfaces for volumes, mounts, drives
|
||||
* and volume monitoring, which return mock data to the caller when used. These
|
||||
* are designed for use in unit tests, to mock up removable drives when testing
|
||||
* code which monitors such drives being added and removed and then queries
|
||||
* properties of them.
|
||||
*
|
||||
* By returning mock drive locations to the caller, for example, the contents of
|
||||
* a removable drive may be mocked up using temporary files.
|
||||
*
|
||||
* Currently, all the mock data returned by these classes to callers is static,
|
||||
* set at construction time.
|
||||
*
|
||||
* Since: 2017.8
|
||||
*/
|
||||
|
||||
/* Mock volume monitor class. This returns a static set of data to the caller,
|
||||
* which it was initialised with. */
|
||||
struct _OstreeMockVolumeMonitor
|
||||
{
|
||||
GVolumeMonitor parent_instance;
|
||||
|
||||
GList *mounts; /* (element-type OstreeMockMount) */
|
||||
GList *volumes; /* (element-type OstreeMockVolume) */
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (OstreeMockVolumeMonitor, ostree_mock_volume_monitor, G_TYPE_VOLUME_MONITOR)
|
||||
|
||||
static GList *
|
||||
ostree_mock_volume_monitor_get_mounts (GVolumeMonitor *monitor)
|
||||
{
|
||||
OstreeMockVolumeMonitor *self = OSTREE_MOCK_VOLUME_MONITOR (monitor);
|
||||
return g_list_copy_deep (self->mounts, (GCopyFunc) g_object_ref, NULL);
|
||||
}
|
||||
|
||||
static GList *
|
||||
ostree_mock_volume_monitor_get_volumes (GVolumeMonitor *monitor)
|
||||
{
|
||||
OstreeMockVolumeMonitor *self = OSTREE_MOCK_VOLUME_MONITOR (monitor);
|
||||
return g_list_copy_deep (self->volumes, (GCopyFunc) g_object_ref, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
ostree_mock_volume_monitor_init (OstreeMockVolumeMonitor *self)
|
||||
{
|
||||
/* Nothing to see here. */
|
||||
}
|
||||
|
||||
static void
|
||||
ostree_mock_volume_monitor_dispose (GObject *object)
|
||||
{
|
||||
OstreeMockVolumeMonitor *self = OSTREE_MOCK_VOLUME_MONITOR (object);
|
||||
|
||||
g_list_free_full (self->volumes, g_object_unref);
|
||||
self->volumes = NULL;
|
||||
|
||||
g_list_free_full (self->mounts, g_object_unref);
|
||||
self->mounts = NULL;
|
||||
|
||||
G_OBJECT_CLASS (ostree_mock_volume_monitor_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
ostree_mock_volume_monitor_class_init (OstreeMockVolumeMonitorClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GVolumeMonitorClass *monitor_class = G_VOLUME_MONITOR_CLASS (klass);
|
||||
|
||||
object_class->dispose = ostree_mock_volume_monitor_dispose;
|
||||
|
||||
monitor_class->get_mounts = ostree_mock_volume_monitor_get_mounts;
|
||||
monitor_class->get_volumes = ostree_mock_volume_monitor_get_volumes;
|
||||
}
|
||||
|
||||
/**
|
||||
* ostree_mock_volume_monitor_new:
|
||||
* @mounts: (element-type GMount) (transfer none): list of current #GMounts
|
||||
* @volumes: (element-type GVolume) (transfer none): list of current #GVolumes
|
||||
*
|
||||
* Create a new mock #GVolumeMonitor which will return the given static lists of
|
||||
* #GMounts and #GVolumes to any caller of g_volume_monitor_get_mounts() or
|
||||
* g_volume_monitor_get_volumes().
|
||||
*
|
||||
* Typically, the elements of @mounts will be #OstreeMockMount objects and the
|
||||
* elements of @volumes will be #OstreeMockVolume objects; but this does not
|
||||
* have to be the case.
|
||||
*
|
||||
* Returns: (transfer full): a new #GVolumeMonitor object
|
||||
* Since: 2017.8
|
||||
*/
|
||||
GVolumeMonitor *
|
||||
ostree_mock_volume_monitor_new (GList *mounts,
|
||||
GList *volumes)
|
||||
{
|
||||
g_autoptr(OstreeMockVolumeMonitor) monitor = NULL;
|
||||
|
||||
monitor = g_object_new (OSTREE_TYPE_MOCK_VOLUME_MONITOR, NULL);
|
||||
monitor->mounts = g_list_copy_deep (mounts, (GCopyFunc) g_object_ref, NULL);
|
||||
monitor->volumes = g_list_copy_deep (volumes, (GCopyFunc) g_object_ref, NULL);
|
||||
|
||||
return g_steal_pointer (&monitor);
|
||||
}
|
||||
|
||||
/* Mock volume class. This returns a static set of data to the caller, which it
|
||||
* was initialised with. */
|
||||
struct _OstreeMockVolume
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
gchar *name;
|
||||
GDrive *drive; /* (owned) (nullable) */
|
||||
GMount *mount; /* (owned) (nullable) */
|
||||
};
|
||||
|
||||
static void ostree_mock_volume_iface_init (GVolumeIface *iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (OstreeMockVolume, ostree_mock_volume, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (G_TYPE_VOLUME, ostree_mock_volume_iface_init))
|
||||
|
||||
static gchar *
|
||||
ostree_mock_volume_get_name (GVolume *volume)
|
||||
{
|
||||
OstreeMockVolume *self = OSTREE_MOCK_VOLUME (volume);
|
||||
return g_strdup (self->name);
|
||||
}
|
||||
|
||||
static GDrive *
|
||||
ostree_mock_volume_get_drive (GVolume *volume)
|
||||
{
|
||||
OstreeMockVolume *self = OSTREE_MOCK_VOLUME (volume);
|
||||
return (self->drive != NULL) ? g_object_ref (self->drive) : NULL;
|
||||
}
|
||||
|
||||
static GMount *
|
||||
ostree_mock_volume_get_mount (GVolume *volume)
|
||||
{
|
||||
OstreeMockVolume *self = OSTREE_MOCK_VOLUME (volume);
|
||||
return (self->mount != NULL) ? g_object_ref (self->mount) : NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
ostree_mock_volume_init (OstreeMockVolume *self)
|
||||
{
|
||||
/* Nothing to see here. */
|
||||
}
|
||||
|
||||
static void
|
||||
ostree_mock_volume_dispose (GObject *object)
|
||||
{
|
||||
OstreeMockVolume *self = OSTREE_MOCK_VOLUME (object);
|
||||
|
||||
g_clear_pointer (&self->name, g_free);
|
||||
g_clear_object (&self->drive);
|
||||
g_clear_object (&self->mount);
|
||||
|
||||
G_OBJECT_CLASS (ostree_mock_volume_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
ostree_mock_volume_class_init (OstreeMockVolumeClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->dispose = ostree_mock_volume_dispose;
|
||||
}
|
||||
|
||||
static void
|
||||
ostree_mock_volume_iface_init (GVolumeIface *iface)
|
||||
{
|
||||
iface->get_name = ostree_mock_volume_get_name;
|
||||
iface->get_drive = ostree_mock_volume_get_drive;
|
||||
iface->get_mount = ostree_mock_volume_get_mount;
|
||||
}
|
||||
|
||||
/**
|
||||
* ostree_mock_volume_new:
|
||||
* @name: volume name
|
||||
* @drive: (transfer none) (nullable): drive for the volume, or %NULL if none
|
||||
* should be associated
|
||||
* @mount: (transfer none) (nullable): mount for the volume, or %NULL if it’s
|
||||
* not mounted
|
||||
*
|
||||
* Create a new mock #GVolume which will return the given static @name, @drive
|
||||
* and @mount to any caller of its getter methods. There is currently no
|
||||
* provision for changing these values dynamically. There is also currently no
|
||||
* provision for mocking the other getters of #GVolume.
|
||||
*
|
||||
* Typically, @drive will be an #OstreeMockDrive object and @mount will be an
|
||||
* #OstreeMockMount object; but this does not have to be the case.
|
||||
*
|
||||
* Returns: (transfer full): a new #GVolume object
|
||||
* Since: 2017.8
|
||||
*/
|
||||
OstreeMockVolume *
|
||||
ostree_mock_volume_new (const gchar *name,
|
||||
GDrive *drive,
|
||||
GMount *mount)
|
||||
{
|
||||
g_autoptr(OstreeMockVolume) volume = NULL;
|
||||
|
||||
volume = g_object_new (OSTREE_TYPE_MOCK_VOLUME, NULL);
|
||||
volume->name = g_strdup (name);
|
||||
volume->drive = (drive != NULL) ? g_object_ref (drive) : NULL;
|
||||
volume->mount = (mount != NULL) ? g_object_ref (mount) : NULL;
|
||||
|
||||
return g_steal_pointer (&volume);
|
||||
}
|
||||
|
||||
/* Mock drive class. This returns a static set of data to the caller, which it
|
||||
* was initialised with. */
|
||||
struct _OstreeMockDrive
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
gboolean is_removable;
|
||||
};
|
||||
|
||||
static void ostree_mock_drive_iface_init (GDriveIface *iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (OstreeMockDrive, ostree_mock_drive, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (G_TYPE_DRIVE, ostree_mock_drive_iface_init))
|
||||
|
||||
#if GLIB_CHECK_VERSION(2, 50, 0)
|
||||
static gboolean
|
||||
ostree_mock_drive_is_removable (GDrive *drive)
|
||||
{
|
||||
OstreeMockDrive *self = OSTREE_MOCK_DRIVE (drive);
|
||||
return self->is_removable;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
ostree_mock_drive_init (OstreeMockDrive *self)
|
||||
{
|
||||
/* Nothing to see here. */
|
||||
}
|
||||
|
||||
static void
|
||||
ostree_mock_drive_class_init (OstreeMockDriveClass *klass)
|
||||
{
|
||||
/* Nothing to see here. */
|
||||
}
|
||||
|
||||
static void
|
||||
ostree_mock_drive_iface_init (GDriveIface *iface)
|
||||
{
|
||||
#if GLIB_CHECK_VERSION(2, 50, 0)
|
||||
iface->is_removable = ostree_mock_drive_is_removable;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* ostree_mock_drive_new:
|
||||
* @is_removable: %TRUE if the drive is removable; %FALSE otherwise
|
||||
*
|
||||
* Create a new mock #GDrive which will return the given static @is_removable to
|
||||
* any caller of its getter methods. There is currently no provision for mocking
|
||||
* the other getters of #GDrive.
|
||||
*
|
||||
* Returns: (transfer full): a new #GDrive object
|
||||
* Since: 2017.8
|
||||
*/
|
||||
OstreeMockDrive *
|
||||
ostree_mock_drive_new (gboolean is_removable)
|
||||
{
|
||||
g_autoptr(OstreeMockDrive) drive = NULL;
|
||||
|
||||
drive = g_object_new (OSTREE_TYPE_MOCK_DRIVE, NULL);
|
||||
drive->is_removable = is_removable;
|
||||
|
||||
return g_steal_pointer (&drive);
|
||||
}
|
||||
|
||||
/* Mock mount class. This returns a static set of data to the caller, which it
|
||||
* was initialised with. */
|
||||
struct _OstreeMockMount
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
gchar *name; /* (owned) */
|
||||
GFile *root; /* (owned) */
|
||||
};
|
||||
|
||||
static void ostree_mock_mount_iface_init (GMountIface *iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (OstreeMockMount, ostree_mock_mount, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (G_TYPE_MOUNT, ostree_mock_mount_iface_init))
|
||||
|
||||
static gchar *
|
||||
ostree_mock_mount_get_name (GMount *mount)
|
||||
{
|
||||
OstreeMockMount *self = OSTREE_MOCK_MOUNT (mount);
|
||||
return g_strdup (self->name);
|
||||
}
|
||||
|
||||
static GFile *
|
||||
ostree_mock_mount_get_root (GMount *mount)
|
||||
{
|
||||
OstreeMockMount *self = OSTREE_MOCK_MOUNT (mount);
|
||||
return g_object_ref (self->root);
|
||||
}
|
||||
|
||||
static void
|
||||
ostree_mock_mount_init (OstreeMockMount *self)
|
||||
{
|
||||
/* Nothing to see here. */
|
||||
}
|
||||
|
||||
static void
|
||||
ostree_mock_mount_dispose (GObject *object)
|
||||
{
|
||||
OstreeMockMount *self = OSTREE_MOCK_MOUNT (object);
|
||||
|
||||
g_clear_pointer (&self->name, g_free);
|
||||
g_clear_object (&self->root);
|
||||
|
||||
G_OBJECT_CLASS (ostree_mock_mount_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
ostree_mock_mount_class_init (OstreeMockMountClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->dispose = ostree_mock_mount_dispose;
|
||||
}
|
||||
|
||||
static void
|
||||
ostree_mock_mount_iface_init (GMountIface *iface)
|
||||
{
|
||||
iface->get_name = ostree_mock_mount_get_name;
|
||||
iface->get_root = ostree_mock_mount_get_root;
|
||||
}
|
||||
|
||||
/**
|
||||
* ostree_mock_mount_new:
|
||||
* @name: mount name
|
||||
* @root: (transfer none): root path for the mounted file system
|
||||
*
|
||||
* Create a new mock #GMount which will return the given static @name and @root
|
||||
* to any caller of its getter methods. There is currently no provision for
|
||||
* mocking the other getters of #GMount.
|
||||
*
|
||||
* Typically, @root will point to a temporary directory where a mocked file
|
||||
* system is present; but this does not have to be the case.
|
||||
*
|
||||
* Returns: (transfer full): a new #GMount object
|
||||
* Since: 2017.8
|
||||
*/
|
||||
OstreeMockMount *
|
||||
ostree_mock_mount_new (const gchar *name,
|
||||
GFile *root)
|
||||
{
|
||||
g_autoptr(OstreeMockMount) mount = NULL;
|
||||
|
||||
mount = g_object_new (OSTREE_TYPE_MOCK_MOUNT, NULL);
|
||||
mount->name = g_strdup (name);
|
||||
mount->root = g_object_ref (root);
|
||||
|
||||
return g_steal_pointer (&mount);
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||||
*
|
||||
* Copyright © 2017 Endless Mobile, Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Authors:
|
||||
* - Philip Withnall <withnall@endlessm.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
#include <libglnx.h>
|
||||
|
||||
#include "ostree-types.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define OSTREE_TYPE_MOCK_VOLUME_MONITOR (ostree_mock_volume_monitor_get_type ())
|
||||
|
||||
/* Manually expanded version of the following, omitting autoptr support (for GLib < 2.44):
|
||||
G_GNUC_INTERNAL
|
||||
G_DECLARE_FINAL_TYPE (OstreeMockVolumeMonitor, ostree_mock_volume_monitor, OSTREE, MOCK_VOLUME_MONITOR, GVolumeMonitor) */
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
GType ostree_mock_volume_monitor_get_type (void);
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
typedef struct _OstreeMockVolumeMonitor OstreeMockVolumeMonitor;
|
||||
typedef struct { GVolumeMonitorClass parent_class; } OstreeMockVolumeMonitorClass;
|
||||
|
||||
static inline OstreeMockVolumeMonitor *OSTREE_MOCK_VOLUME_MONITOR (gpointer ptr) { return G_TYPE_CHECK_INSTANCE_CAST (ptr, ostree_mock_volume_monitor_get_type (), OstreeMockVolumeMonitor); }
|
||||
static inline gboolean OSTREE_IS_MOCK_VOLUME_MONITOR (gpointer ptr) { return G_TYPE_CHECK_INSTANCE_TYPE (ptr, ostree_mock_volume_monitor_get_type ()); }
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeMockVolumeMonitor, g_object_unref)
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
GVolumeMonitor *ostree_mock_volume_monitor_new (GList *mounts,
|
||||
GList *volumes);
|
||||
|
||||
#define OSTREE_TYPE_MOCK_VOLUME (ostree_mock_volume_get_type ())
|
||||
|
||||
/* Manually expanded version of the following, omitting autoptr support (for GLib < 2.44):
|
||||
G_GNUC_INTERNAL
|
||||
G_DECLARE_FINAL_TYPE (OstreeMockVolume, ostree_mock_volume, OSTREE, MOCK_VOLUME, GObject) */
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
GType ostree_mock_volume_get_type (void);
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
typedef struct _OstreeMockVolume OstreeMockVolume;
|
||||
typedef struct { GObjectClass parent_class; } OstreeMockVolumeClass;
|
||||
|
||||
static inline OstreeMockVolume *OSTREE_MOCK_VOLUME (gpointer ptr) { return G_TYPE_CHECK_INSTANCE_CAST (ptr, ostree_mock_volume_get_type (), OstreeMockVolume); }
|
||||
static inline gboolean OSTREE_IS_MOCK_VOLUME (gpointer ptr) { return G_TYPE_CHECK_INSTANCE_TYPE (ptr, ostree_mock_volume_get_type ()); }
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeMockVolume, g_object_unref)
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
OstreeMockVolume *ostree_mock_volume_new (const gchar *name,
|
||||
GDrive *drive,
|
||||
GMount *mount);
|
||||
|
||||
#define OSTREE_TYPE_MOCK_DRIVE (ostree_mock_drive_get_type ())
|
||||
|
||||
/* Manually expanded version of the following, omitting autoptr support (for GLib < 2.44):
|
||||
G_GNUC_INTERNAL
|
||||
G_DECLARE_FINAL_TYPE (OstreeMockDrive, ostree_mock_drive, OSTREE, MOCK_DRIVE, GObject) */
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
GType ostree_mock_drive_get_type (void);
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
typedef struct _OstreeMockDrive OstreeMockDrive;
|
||||
typedef struct { GObjectClass parent_class; } OstreeMockDriveClass;
|
||||
|
||||
static inline OstreeMockDrive *OSTREE_MOCK_DRIVE (gpointer ptr) { return G_TYPE_CHECK_INSTANCE_CAST (ptr, ostree_mock_drive_get_type (), OstreeMockDrive); }
|
||||
static inline gboolean OSTREE_IS_MOCK_DRIVE (gpointer ptr) { return G_TYPE_CHECK_INSTANCE_TYPE (ptr, ostree_mock_drive_get_type ()); }
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeMockDrive, g_object_unref)
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
OstreeMockDrive *ostree_mock_drive_new (gboolean is_removable);
|
||||
|
||||
#define OSTREE_TYPE_MOCK_MOUNT (ostree_mock_mount_get_type ())
|
||||
|
||||
/* Manually expanded version of the following, omitting autoptr support (for GLib < 2.44):
|
||||
G_GNUC_INTERNAL
|
||||
G_DECLARE_FINAL_TYPE (OstreeMockMount, ostree_mock_mount, OSTREE, MOCK_MOUNT, GObject) */
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
GType ostree_mock_mount_get_type (void);
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
typedef struct _OstreeMockMount OstreeMockMount;
|
||||
typedef struct { GObjectClass parent_class; } OstreeMockMountClass;
|
||||
|
||||
static inline OstreeMockMount *OSTREE_MOCK_MOUNT (gpointer ptr) { return G_TYPE_CHECK_INSTANCE_CAST (ptr, ostree_mock_mount_get_type (), OstreeMockMount); }
|
||||
static inline gboolean OSTREE_IS_MOCK_MOUNT (gpointer ptr) { return G_TYPE_CHECK_INSTANCE_TYPE (ptr, ostree_mock_mount_get_type ()); }
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeMockMount, g_object_unref)
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
OstreeMockMount *ostree_mock_mount_new (const gchar *name,
|
||||
GFile *root);
|
||||
|
||||
G_END_DECLS
|
||||
@@ -21,6 +21,6 @@ set -euo pipefail
|
||||
|
||||
. $(dirname $0)/libtest.sh
|
||||
|
||||
setup_fake_remote_repo1 "archive-z2"
|
||||
setup_fake_remote_repo1 "archive"
|
||||
|
||||
. ${test_srcdir}/pull-test.sh
|
||||
+1
-1
@@ -43,7 +43,7 @@ test_data_init (TestData *td)
|
||||
if (!td->repo)
|
||||
goto out;
|
||||
|
||||
if (!ot_test_run_libtest ("setup_fake_remote_repo1 archive-z2", error))
|
||||
if (!ot_test_run_libtest ("setup_fake_remote_repo1 archive", error))
|
||||
goto out;
|
||||
|
||||
if (!g_file_get_contents ("httpd-address", &http_address, NULL, error))
|
||||
|
||||
Executable
+45
@@ -0,0 +1,45 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright (C) 2017 Red Hat, Inc.
|
||||
#
|
||||
# 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
|
||||
|
||||
. $(dirname $0)/libtest.sh
|
||||
|
||||
setup_fake_remote_repo1 "archive"
|
||||
|
||||
echo '1..1'
|
||||
|
||||
cd ${test_tmpdir}
|
||||
gnomerepo_url="$(cat httpd-address)/ostree/gnomerepo"
|
||||
ostree_repo_init repo --mode "archive"
|
||||
ostree_repo_init repo-local --mode "archive"
|
||||
for repo in repo{,-local}; do
|
||||
${CMD_PREFIX} ostree --repo=${repo} remote add --set=gpg-verify=false origin ${gnomerepo_url}
|
||||
done
|
||||
|
||||
# Pull the contents to our local cache
|
||||
${CMD_PREFIX} ostree --repo=repo-local pull origin main
|
||||
rm files -rf
|
||||
${CMD_PREFIX} ostree --repo=ostree-srv/gnomerepo checkout main files
|
||||
echo anewfile > files/anewfile
|
||||
${CMD_PREFIX} ostree --repo=ostree-srv/gnomerepo commit -b main --tree=dir=files
|
||||
|
||||
${CMD_PREFIX} ostree --repo=repo pull -L repo-local origin main >out.txt
|
||||
assert_file_has_content out.txt '3 metadata, 1 content objects fetched (4 meta, 5 content local)'
|
||||
echo "ok pull --reference"
|
||||
@@ -0,0 +1,228 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||||
*
|
||||
* Copyright © 2017 Endless Mobile, Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Authors:
|
||||
* - Philip Withnall <withnall@endlessm.com>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
#include <locale.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ostree-autocleanups.h"
|
||||
#include "ostree-repo-finder.h"
|
||||
#include "ostree-repo-finder-avahi.h"
|
||||
#include "ostree-repo-finder-avahi-private.h"
|
||||
|
||||
/* FIXME: Upstream this */
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (AvahiStringList, avahi_string_list_free)
|
||||
|
||||
/* Test the object constructor works at a basic level. */
|
||||
static void
|
||||
test_repo_finder_avahi_init (void)
|
||||
{
|
||||
g_autoptr(OstreeRepoFinderAvahi) finder = NULL;
|
||||
g_autoptr(GMainContext) context = NULL;
|
||||
|
||||
/* Default main context. */
|
||||
finder = ostree_repo_finder_avahi_new (NULL);
|
||||
g_clear_object (&finder);
|
||||
|
||||
/* Explicit main context. */
|
||||
context = g_main_context_new ();
|
||||
finder = ostree_repo_finder_avahi_new (context);
|
||||
g_clear_object (&finder);
|
||||
}
|
||||
|
||||
/* Test parsing valid and invalid TXT records. */
|
||||
static void
|
||||
test_repo_finder_avahi_txt_records_parse (void)
|
||||
{
|
||||
struct
|
||||
{
|
||||
const guint8 *txt;
|
||||
gsize txt_len;
|
||||
const gchar *expected_key; /* (nullable) to indicate parse failure */
|
||||
const guint8 *expected_value; /* (nullable) to allow for valueless keys */
|
||||
gsize expected_value_len;
|
||||
}
|
||||
vectors[] =
|
||||
{
|
||||
{ (const guint8 *) "", 0, NULL, NULL, 0 },
|
||||
{ (const guint8 *) "\x00", 1, NULL, NULL, 0 },
|
||||
{ (const guint8 *) "\xff", 1, NULL, NULL, 0 },
|
||||
{ (const guint8 *) "k\x00", 2, NULL, NULL, 0 },
|
||||
{ (const guint8 *) "k\xff", 2, NULL, NULL, 0 },
|
||||
{ (const guint8 *) "=", 1, NULL, NULL, 0 },
|
||||
{ (const guint8 *) "=value", 6, NULL, NULL, 0 },
|
||||
{ (const guint8 *) "k=v", 3, "k", (const guint8 *) "v", 1 },
|
||||
{ (const guint8 *) "key=value", 9, "key", (const guint8 *) "value", 5 },
|
||||
{ (const guint8 *) "k=v=", 4, "k", (const guint8 *) "v=", 2 },
|
||||
{ (const guint8 *) "k=", 2, "k", (const guint8 *) "", 0 },
|
||||
{ (const guint8 *) "k", 1, "k", NULL, 0 },
|
||||
{ (const guint8 *) "k==", 3, "k", (const guint8 *) "=", 1 },
|
||||
{ (const guint8 *) "k=\x00\x01\x02", 5, "k", (const guint8 *) "\x00\x01\x02", 3 },
|
||||
};
|
||||
gsize i;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (vectors); i++)
|
||||
{
|
||||
g_autoptr(AvahiStringList) string_list = NULL;
|
||||
g_autoptr(GHashTable) attributes = NULL;
|
||||
|
||||
g_test_message ("Vector %" G_GSIZE_FORMAT, i);
|
||||
|
||||
string_list = avahi_string_list_add_arbitrary (NULL, vectors[i].txt, vectors[i].txt_len);
|
||||
|
||||
attributes = _ostree_txt_records_parse (string_list);
|
||||
|
||||
if (vectors[i].expected_key != NULL)
|
||||
{
|
||||
GBytes *value;
|
||||
g_autoptr(GBytes) expected_value = NULL;
|
||||
|
||||
g_assert_true (g_hash_table_lookup_extended (attributes,
|
||||
vectors[i].expected_key,
|
||||
NULL,
|
||||
(gpointer *) &value));
|
||||
g_assert_cmpuint (g_hash_table_size (attributes), ==, 1);
|
||||
|
||||
if (vectors[i].expected_value != NULL)
|
||||
{
|
||||
g_assert_nonnull (value);
|
||||
expected_value = g_bytes_new_static (vectors[i].expected_value, vectors[i].expected_value_len);
|
||||
g_assert_true (g_bytes_equal (value, expected_value));
|
||||
}
|
||||
else
|
||||
{
|
||||
g_assert_null (value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_assert_cmpuint (g_hash_table_size (attributes), ==, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Test that the first value for a set of duplicate records is returned.
|
||||
* See RFC 6763, §6.4. */
|
||||
static void
|
||||
test_repo_finder_avahi_txt_records_duplicates (void)
|
||||
{
|
||||
g_autoptr(AvahiStringList) string_list = NULL;
|
||||
g_autoptr(GHashTable) attributes = NULL;
|
||||
GBytes *value;
|
||||
g_autoptr(GBytes) expected_value = NULL;
|
||||
|
||||
/* Reverse the list before using it, as they are built in reverse order.
|
||||
* (See the #AvahiStringList documentation.) */
|
||||
string_list = avahi_string_list_new ("k=value1", "k=value2", "k=value3", NULL);
|
||||
string_list = avahi_string_list_reverse (string_list);
|
||||
attributes = _ostree_txt_records_parse (string_list);
|
||||
|
||||
g_assert_cmpuint (g_hash_table_size (attributes), ==, 1);
|
||||
value = g_hash_table_lookup (attributes, "k");
|
||||
g_assert_nonnull (value);
|
||||
|
||||
expected_value = g_bytes_new_static ("value1", strlen ("value1"));
|
||||
g_assert_true (g_bytes_equal (value, expected_value));
|
||||
}
|
||||
|
||||
/* Test that keys are parsed and looked up case insensitively.
|
||||
* See RFC 6763, §6.4. */
|
||||
static void
|
||||
test_repo_finder_avahi_txt_records_case_sensitivity (void)
|
||||
{
|
||||
g_autoptr(AvahiStringList) string_list = NULL;
|
||||
g_autoptr(GHashTable) attributes = NULL;
|
||||
GBytes *value1, *value2;
|
||||
g_autoptr(GBytes) expected_value1 = NULL, expected_value2 = NULL;
|
||||
|
||||
/* Reverse the list before using it, as they are built in reverse order.
|
||||
* (See the #AvahiStringList documentation.) */
|
||||
string_list = avahi_string_list_new ("k=value1",
|
||||
"K=value2",
|
||||
"KeY2=v",
|
||||
NULL);
|
||||
string_list = avahi_string_list_reverse (string_list);
|
||||
attributes = _ostree_txt_records_parse (string_list);
|
||||
|
||||
g_assert_cmpuint (g_hash_table_size (attributes), ==, 2);
|
||||
|
||||
value1 = g_hash_table_lookup (attributes, "k");
|
||||
g_assert_nonnull (value1);
|
||||
expected_value1 = g_bytes_new_static ("value1", strlen ("value1"));
|
||||
g_assert_true (g_bytes_equal (value1, expected_value1));
|
||||
|
||||
g_assert_null (g_hash_table_lookup (attributes, "K"));
|
||||
|
||||
value2 = g_hash_table_lookup (attributes, "key2");
|
||||
g_assert_nonnull (value2);
|
||||
expected_value2 = g_bytes_new_static ("v", 1);
|
||||
g_assert_true (g_bytes_equal (value2, expected_value2));
|
||||
|
||||
g_assert_null (g_hash_table_lookup (attributes, "KeY2"));
|
||||
}
|
||||
|
||||
/* Test that keys which have an empty value can be distinguished from those
|
||||
* which have no value. See RFC 6763, §6.4. */
|
||||
static void
|
||||
test_repo_finder_avahi_txt_records_empty_and_missing (void)
|
||||
{
|
||||
g_autoptr(AvahiStringList) string_list = NULL;
|
||||
g_autoptr(GHashTable) attributes = NULL;
|
||||
GBytes *value1, *value2;
|
||||
g_autoptr(GBytes) expected_value1 = NULL;
|
||||
|
||||
string_list = avahi_string_list_new ("empty=",
|
||||
"missing",
|
||||
NULL);
|
||||
attributes = _ostree_txt_records_parse (string_list);
|
||||
|
||||
g_assert_cmpuint (g_hash_table_size (attributes), ==, 2);
|
||||
|
||||
value1 = g_hash_table_lookup (attributes, "empty");
|
||||
g_assert_nonnull (value1);
|
||||
expected_value1 = g_bytes_new_static ("", 0);
|
||||
g_assert_true (g_bytes_equal (value1, expected_value1));
|
||||
|
||||
g_assert_true (g_hash_table_lookup_extended (attributes, "missing", NULL, (gpointer *) &value2));
|
||||
g_assert_null (value2);
|
||||
}
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
setlocale (LC_ALL, "");
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
|
||||
g_test_add_func ("/repo-finder-avahi/init", test_repo_finder_avahi_init);
|
||||
g_test_add_func ("/repo-finder-avahi/txt-records/parse", test_repo_finder_avahi_txt_records_parse);
|
||||
g_test_add_func ("/repo-finder-avahi/txt-records/duplicates", test_repo_finder_avahi_txt_records_duplicates);
|
||||
g_test_add_func ("/repo-finder-avahi/txt-records/case-sensitivity", test_repo_finder_avahi_txt_records_case_sensitivity);
|
||||
g_test_add_func ("/repo-finder-avahi/txt-records/empty-and-missing", test_repo_finder_avahi_txt_records_empty_and_missing);
|
||||
/* FIXME: Add tests for service processing, probably by splitting the
|
||||
* code in OstreeRepoFinderAvahi around found_services. */
|
||||
|
||||
return g_test_run();
|
||||
}
|
||||
@@ -0,0 +1,327 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||||
*
|
||||
* Copyright © 2017 Endless Mobile, Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Authors:
|
||||
* - Philip Withnall <withnall@endlessm.com>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
#include <libglnx.h>
|
||||
#include <locale.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "libostreetest.h"
|
||||
#include "ostree-autocleanups.h"
|
||||
#include "ostree-repo-finder.h"
|
||||
#include "ostree-repo-finder-config.h"
|
||||
|
||||
/* Test fixture. Creates a temporary directory. */
|
||||
typedef struct
|
||||
{
|
||||
OstreeRepo *parent_repo; /* owned */
|
||||
int working_dfd; /* owned */
|
||||
GFile *working_dir; /* owned */
|
||||
} Fixture;
|
||||
|
||||
static void
|
||||
setup (Fixture *fixture,
|
||||
gconstpointer test_data)
|
||||
{
|
||||
g_autofree gchar *tmp_name = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
tmp_name = g_strdup ("test-repo-finder-config-XXXXXX");
|
||||
glnx_mkdtempat_open_in_system (tmp_name, 0700, &fixture->working_dfd, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
g_test_message ("Using temporary directory: %s", tmp_name);
|
||||
|
||||
glnx_shutil_mkdir_p_at (fixture->working_dfd, "repo", 0700, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
g_autoptr(GFile) tmp_dir = g_file_new_for_path (g_get_tmp_dir ());
|
||||
fixture->working_dir = g_file_get_child (tmp_dir, tmp_name);
|
||||
|
||||
fixture->parent_repo = ot_test_setup_repo (NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
}
|
||||
|
||||
static void
|
||||
teardown (Fixture *fixture,
|
||||
gconstpointer test_data)
|
||||
{
|
||||
glnx_fd_close int parent_repo_dfd = -1;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
/* Recursively remove the temporary directory. */
|
||||
glnx_shutil_rm_rf_at (fixture->working_dfd, ".", NULL, NULL);
|
||||
|
||||
close (fixture->working_dfd);
|
||||
fixture->working_dfd = -1;
|
||||
|
||||
/* The repo also needs its source files to be removed. This is the inverse
|
||||
* of setup_test_repository() in libtest.sh. */
|
||||
g_autofree gchar *parent_repo_path = g_file_get_path (ostree_repo_get_path (fixture->parent_repo));
|
||||
glnx_opendirat (-1, parent_repo_path, TRUE, &parent_repo_dfd, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
glnx_shutil_rm_rf_at (parent_repo_dfd, "../files", NULL, NULL);
|
||||
glnx_shutil_rm_rf_at (parent_repo_dfd, "../repo", NULL, NULL);
|
||||
|
||||
g_clear_object (&fixture->working_dir);
|
||||
g_clear_object (&fixture->parent_repo);
|
||||
}
|
||||
|
||||
/* Test the object constructor works at a basic level. */
|
||||
static void
|
||||
test_repo_finder_config_init (void)
|
||||
{
|
||||
g_autoptr(OstreeRepoFinderConfig) finder = NULL;
|
||||
|
||||
/* Default everything. */
|
||||
finder = ostree_repo_finder_config_new ();
|
||||
}
|
||||
|
||||
static void
|
||||
result_cb (GObject *source_object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
GAsyncResult **result_out = user_data;
|
||||
*result_out = g_object_ref (result);
|
||||
}
|
||||
|
||||
/* Test that no remotes are found if there are no config files in the refs
|
||||
* directory. */
|
||||
static void
|
||||
test_repo_finder_config_no_configs (Fixture *fixture,
|
||||
gconstpointer test_data)
|
||||
{
|
||||
g_autoptr(OstreeRepoFinderConfig) finder = NULL;
|
||||
g_autoptr(GMainContext) context = NULL;
|
||||
g_autoptr(GAsyncResult) result = NULL;
|
||||
g_autoptr(GPtrArray) results = NULL; /* (element-type OstreeRepoFinderResult) */
|
||||
g_autoptr(GError) error = NULL;
|
||||
const OstreeCollectionRef ref1 = { "org.example.Os", "exampleos/x86_64/standard" };
|
||||
const OstreeCollectionRef ref2 = { "org.example.Os", "exampleos/x86_64/buildmaster/standard" };
|
||||
const OstreeCollectionRef * const refs[] = { &ref1, &ref2, NULL };
|
||||
|
||||
context = g_main_context_new ();
|
||||
g_main_context_push_thread_default (context);
|
||||
|
||||
finder = ostree_repo_finder_config_new ();
|
||||
|
||||
ostree_repo_finder_resolve_async (OSTREE_REPO_FINDER (finder), refs,
|
||||
fixture->parent_repo, NULL, result_cb, &result);
|
||||
|
||||
while (result == NULL)
|
||||
g_main_context_iteration (context, TRUE);
|
||||
|
||||
results = ostree_repo_finder_resolve_finish (OSTREE_REPO_FINDER (finder),
|
||||
result, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert_nonnull (results);
|
||||
g_assert_cmpuint (results->len, ==, 0);
|
||||
|
||||
g_main_context_pop_thread_default (context);
|
||||
}
|
||||
|
||||
/* Add configuration for a remote named @remote_name, at @remote_uri, with a
|
||||
* remote collection ID of @collection_id, to the given @repo. */
|
||||
static void
|
||||
assert_create_remote_config (OstreeRepo *repo,
|
||||
const gchar *remote_name,
|
||||
const gchar *remote_uri,
|
||||
const gchar *collection_id)
|
||||
{
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autoptr(GVariant) options = NULL;
|
||||
|
||||
if (collection_id != NULL)
|
||||
options = g_variant_new_parsed ("@a{sv} { 'collection-id': <%s> }",
|
||||
collection_id);
|
||||
|
||||
ostree_repo_remote_add (repo, remote_name, remote_uri, options, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
}
|
||||
|
||||
static gchar *assert_create_remote (Fixture *fixture,
|
||||
const gchar *collection_id,
|
||||
...) G_GNUC_NULL_TERMINATED;
|
||||
|
||||
/* Create a new repository in a temporary directory with its collection ID set
|
||||
* to @collection_id, and containing the refs given in @... (which must be
|
||||
* %NULL-terminated). Return the `file://` URI of the new repository. */
|
||||
static gchar *
|
||||
assert_create_remote (Fixture *fixture,
|
||||
const gchar *collection_id,
|
||||
...)
|
||||
{
|
||||
va_list args;
|
||||
g_autoptr(GError) error = NULL;
|
||||
const gchar *repo_name = (collection_id != NULL) ? collection_id : "no-collection";
|
||||
|
||||
glnx_shutil_mkdir_p_at (fixture->working_dfd, repo_name, 0700, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
g_autoptr(GFile) repo_path = g_file_get_child (fixture->working_dir, repo_name);
|
||||
g_autoptr(OstreeRepo) repo = ostree_repo_new (repo_path);
|
||||
ostree_repo_set_collection_id (repo, collection_id, &error);
|
||||
g_assert_no_error (error);
|
||||
ostree_repo_create (repo, OSTREE_REPO_MODE_ARCHIVE_Z2, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
/* Set up the refs from @.... */
|
||||
va_start (args, collection_id);
|
||||
|
||||
for (const gchar *ref_name = va_arg (args, const gchar *);
|
||||
ref_name != NULL;
|
||||
ref_name = va_arg (args, const gchar *))
|
||||
{
|
||||
OstreeCollectionRef collection_ref = { (gchar *) collection_id, (gchar *) ref_name };
|
||||
g_autofree gchar *checksum = NULL;
|
||||
g_autoptr(OstreeMutableTree) mtree = NULL;
|
||||
g_autoptr(OstreeRepoFile) repo_file = NULL;
|
||||
|
||||
mtree = ostree_mutable_tree_new ();
|
||||
ostree_repo_write_dfd_to_mtree (repo, AT_FDCWD, ".", mtree, NULL, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
ostree_repo_write_mtree (repo, mtree, (GFile **) &repo_file, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
ostree_repo_write_commit (repo, NULL /* no parent */, ref_name, ref_name,
|
||||
NULL /* no metadata */, repo_file, &checksum,
|
||||
NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
if (collection_id != NULL)
|
||||
ostree_repo_set_collection_ref_immediate (repo, &collection_ref, checksum, NULL, &error);
|
||||
else
|
||||
ostree_repo_set_ref_immediate (repo, NULL, ref_name, checksum, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
}
|
||||
|
||||
va_end (args);
|
||||
|
||||
/* Update the summary. */
|
||||
ostree_repo_regenerate_summary (repo, NULL /* no metadata */, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
return g_file_get_uri (repo_path);
|
||||
}
|
||||
|
||||
/* Test resolving the refs against a collection of config files, which contain
|
||||
* valid, invalid or duplicate repo information. */
|
||||
static void
|
||||
test_repo_finder_config_mixed_configs (Fixture *fixture,
|
||||
gconstpointer test_data)
|
||||
{
|
||||
g_autoptr(OstreeRepoFinderConfig) finder = NULL;
|
||||
g_autoptr(GMainContext) context = NULL;
|
||||
g_autoptr(GAsyncResult) result = NULL;
|
||||
g_autoptr(GPtrArray) results = NULL; /* (element-type OstreeRepoFinderResult) */
|
||||
g_autoptr(GError) error = NULL;
|
||||
gsize i;
|
||||
const OstreeCollectionRef ref0 = { "org.example.Collection0", "exampleos/x86_64/ref0" };
|
||||
const OstreeCollectionRef ref1 = { "org.example.Collection0", "exampleos/x86_64/ref1" };
|
||||
const OstreeCollectionRef ref2 = { "org.example.Collection1", "exampleos/x86_64/ref1" };
|
||||
const OstreeCollectionRef ref3 = { "org.example.Collection1", "exampleos/x86_64/ref2" };
|
||||
const OstreeCollectionRef ref4 = { "org.example.Collection2", "exampleos/x86_64/ref3" };
|
||||
const OstreeCollectionRef * const refs[] = { &ref0, &ref1, &ref2, &ref3, &ref4, NULL };
|
||||
|
||||
context = g_main_context_new ();
|
||||
g_main_context_push_thread_default (context);
|
||||
|
||||
/* Put together various ref configuration files. */
|
||||
g_autofree gchar *collection0_uri = assert_create_remote (fixture, "org.example.Collection0",
|
||||
"exampleos/x86_64/ref0",
|
||||
"exampleos/x86_64/ref1",
|
||||
NULL);
|
||||
g_autofree gchar *collection1_uri = assert_create_remote (fixture, "org.example.Collection1",
|
||||
"exampleos/x86_64/ref2",
|
||||
NULL);
|
||||
g_autofree gchar *no_collection_uri = assert_create_remote (fixture, NULL,
|
||||
"exampleos/x86_64/ref3",
|
||||
NULL);
|
||||
|
||||
assert_create_remote_config (fixture->parent_repo, "remote0", collection0_uri, "org.example.Collection0");
|
||||
assert_create_remote_config (fixture->parent_repo, "remote1", collection1_uri, "org.example.Collection1");
|
||||
assert_create_remote_config (fixture->parent_repo, "remote0-copy", collection0_uri, "org.example.Collection0");
|
||||
assert_create_remote_config (fixture->parent_repo, "remote1-bad-copy", collection1_uri, "org.example.NotCollection1");
|
||||
assert_create_remote_config (fixture->parent_repo, "remote2", no_collection_uri, NULL);
|
||||
|
||||
finder = ostree_repo_finder_config_new ();
|
||||
|
||||
/* Resolve the refs. */
|
||||
ostree_repo_finder_resolve_async (OSTREE_REPO_FINDER (finder), refs,
|
||||
fixture->parent_repo, NULL, result_cb, &result);
|
||||
|
||||
while (result == NULL)
|
||||
g_main_context_iteration (context, TRUE);
|
||||
|
||||
results = ostree_repo_finder_resolve_finish (OSTREE_REPO_FINDER (finder),
|
||||
result, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert_nonnull (results);
|
||||
g_assert_cmpuint (results->len, ==, 3);
|
||||
|
||||
/* Check that the results are correct: the invalid refs should have been
|
||||
* ignored, and the valid results canonicalised and deduplicated. */
|
||||
for (i = 0; i < results->len; i++)
|
||||
{
|
||||
const OstreeRepoFinderResult *result = g_ptr_array_index (results, i);
|
||||
|
||||
if (g_strcmp0 (ostree_remote_get_name (result->remote), "remote0") == 0 ||
|
||||
g_strcmp0 (ostree_remote_get_name (result->remote), "remote0-copy") == 0)
|
||||
{
|
||||
g_assert_cmpuint (g_hash_table_size (result->ref_to_checksum), ==, 2);
|
||||
g_assert_true (g_hash_table_contains (result->ref_to_checksum, &ref0));
|
||||
g_assert_true (g_hash_table_contains (result->ref_to_checksum, &ref1));
|
||||
}
|
||||
else if (g_strcmp0 (ostree_remote_get_name (result->remote), "remote1") == 0)
|
||||
{
|
||||
g_assert_cmpuint (g_hash_table_size (result->ref_to_checksum), ==, 1);
|
||||
g_assert_true (g_hash_table_contains (result->ref_to_checksum, &ref3));
|
||||
}
|
||||
else
|
||||
{
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
g_main_context_pop_thread_default (context);
|
||||
}
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
setlocale (LC_ALL, "");
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
|
||||
g_test_add_func ("/repo-finder-config/init", test_repo_finder_config_init);
|
||||
g_test_add ("/repo-finder-config/no-configs", Fixture, NULL, setup,
|
||||
test_repo_finder_config_no_configs, teardown);
|
||||
g_test_add ("/repo-finder-config/mixed-configs", Fixture, NULL, setup,
|
||||
test_repo_finder_config_mixed_configs, teardown);
|
||||
|
||||
return g_test_run();
|
||||
}
|
||||
@@ -0,0 +1,497 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||||
*
|
||||
* Copyright © 2017 Endless Mobile, Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Authors:
|
||||
* - Philip Withnall <withnall@endlessm.com>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
#include <locale.h>
|
||||
|
||||
#include "libostreetest.h"
|
||||
#include "ostree-autocleanups.h"
|
||||
#include "ostree-remote-private.h"
|
||||
#include "ostree-repo-finder.h"
|
||||
#include "ostree-repo-finder-mount.h"
|
||||
#include "ostree-types.h"
|
||||
#include "test-mock-gio.h"
|
||||
|
||||
/* Test fixture. Creates a temporary directory and repository. */
|
||||
typedef struct
|
||||
{
|
||||
OstreeRepo *parent_repo;
|
||||
int working_dfd; /* owned */
|
||||
GFile *working_dir; /* owned */
|
||||
} Fixture;
|
||||
|
||||
static void
|
||||
setup (Fixture *fixture,
|
||||
gconstpointer test_data)
|
||||
{
|
||||
g_autofree gchar *tmp_name = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
tmp_name = g_strdup ("test-repo-finder-mount-XXXXXX");
|
||||
glnx_mkdtempat_open_in_system (tmp_name, 0700, &fixture->working_dfd, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
g_test_message ("Using temporary directory: %s", tmp_name);
|
||||
|
||||
glnx_shutil_mkdir_p_at (fixture->working_dfd, "repo", 0700, NULL, &error);
|
||||
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS))
|
||||
g_clear_error (&error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
g_autoptr(GFile) tmp_dir = g_file_new_for_path (g_get_tmp_dir ());
|
||||
fixture->working_dir = g_file_get_child (tmp_dir, tmp_name);
|
||||
|
||||
fixture->parent_repo = ot_test_setup_repo (NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
}
|
||||
|
||||
static void
|
||||
teardown (Fixture *fixture,
|
||||
gconstpointer test_data)
|
||||
{
|
||||
glnx_fd_close int parent_repo_dfd = -1;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
/* Recursively remove the temporary directory. */
|
||||
glnx_shutil_rm_rf_at (fixture->working_dfd, ".", NULL, NULL);
|
||||
|
||||
close (fixture->working_dfd);
|
||||
fixture->working_dfd = -1;
|
||||
|
||||
/* The repo also needs its source files to be removed. This is the inverse
|
||||
* of setup_test_repository() in libtest.sh. */
|
||||
g_autofree gchar *parent_repo_path = g_file_get_path (ostree_repo_get_path (fixture->parent_repo));
|
||||
glnx_opendirat (-1, parent_repo_path, TRUE, &parent_repo_dfd, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
glnx_shutil_rm_rf_at (parent_repo_dfd, "../files", NULL, NULL);
|
||||
glnx_shutil_rm_rf_at (parent_repo_dfd, "../repo", NULL, NULL);
|
||||
|
||||
g_clear_object (&fixture->working_dir);
|
||||
g_clear_object (&fixture->parent_repo);
|
||||
}
|
||||
|
||||
/* Test the object constructor works at a basic level. */
|
||||
static void
|
||||
test_repo_finder_mount_init (void)
|
||||
{
|
||||
g_autoptr(OstreeRepoFinderMount) finder = NULL;
|
||||
g_autoptr(GVolumeMonitor) monitor = NULL;
|
||||
|
||||
/* Default #GVolumeMonitor. */
|
||||
finder = ostree_repo_finder_mount_new (NULL);
|
||||
g_clear_object (&finder);
|
||||
|
||||
/* Explicit #GVolumeMonitor. */
|
||||
monitor = ostree_mock_volume_monitor_new (NULL, NULL);
|
||||
finder = ostree_repo_finder_mount_new (monitor);
|
||||
g_clear_object (&finder);
|
||||
}
|
||||
|
||||
static void
|
||||
result_cb (GObject *source_object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
GAsyncResult **result_out = user_data;
|
||||
*result_out = g_object_ref (result);
|
||||
}
|
||||
|
||||
/* Test that no remotes are found if the #GVolumeMonitor returns no mounts. */
|
||||
static void
|
||||
test_repo_finder_mount_no_mounts (Fixture *fixture,
|
||||
gconstpointer test_data)
|
||||
{
|
||||
g_autoptr(OstreeRepoFinderMount) finder = NULL;
|
||||
g_autoptr(GVolumeMonitor) monitor = NULL;
|
||||
g_autoptr(GMainContext) context = NULL;
|
||||
g_autoptr(GAsyncResult) result = NULL;
|
||||
g_autoptr(GPtrArray) results = NULL; /* (element-type OstreeRepoFinderResult) */
|
||||
g_autoptr(GError) error = NULL;
|
||||
const OstreeCollectionRef ref1 = { "org.example.Collection1", "exampleos/x86_64/standard" };
|
||||
const OstreeCollectionRef ref2 = { "org.example.Collection1", "exampleos/x86_64/buildmaster/standard" };
|
||||
const OstreeCollectionRef ref3 = { "org.example.Collection2", "exampleos/x86_64/standard" };
|
||||
const OstreeCollectionRef ref4 = { "org.example.Collection2", "exampleos/arm64/standard" };
|
||||
const OstreeCollectionRef * const refs[] = { &ref1, &ref2, &ref3, &ref4, NULL };
|
||||
|
||||
context = g_main_context_new ();
|
||||
g_main_context_push_thread_default (context);
|
||||
|
||||
monitor = ostree_mock_volume_monitor_new (NULL, NULL);
|
||||
finder = ostree_repo_finder_mount_new (monitor);
|
||||
|
||||
ostree_repo_finder_resolve_async (OSTREE_REPO_FINDER (finder), refs,
|
||||
fixture->parent_repo,
|
||||
NULL, result_cb, &result);
|
||||
|
||||
while (result == NULL)
|
||||
g_main_context_iteration (context, TRUE);
|
||||
|
||||
results = ostree_repo_finder_resolve_finish (OSTREE_REPO_FINDER (finder),
|
||||
result, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert_nonnull (results);
|
||||
g_assert_cmpuint (results->len, ==, 0);
|
||||
|
||||
g_main_context_pop_thread_default (context);
|
||||
}
|
||||
|
||||
/* Create a .ostree/repos directory under the given @mount_root, or abort. */
|
||||
static gboolean
|
||||
assert_create_repos_dir (Fixture *fixture,
|
||||
const gchar *mount_root_name,
|
||||
int *out_repos_dfd,
|
||||
GMount **out_mount)
|
||||
{
|
||||
glnx_fd_close int repos_dfd = -1;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
g_autofree gchar *path = g_build_filename (mount_root_name, ".ostree", "repos", NULL);
|
||||
glnx_shutil_mkdir_p_at_open (fixture->working_dfd, path, 0700, &repos_dfd, NULL, &error);
|
||||
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS))
|
||||
g_clear_error (&error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
*out_repos_dfd = glnx_steal_fd (&repos_dfd);
|
||||
g_autoptr(GFile) mount_root = g_file_get_child (fixture->working_dir, mount_root_name);
|
||||
*out_mount = G_MOUNT (ostree_mock_mount_new (mount_root_name, mount_root));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Create a new repository in @repo_dir with its collection ID unset, and
|
||||
* containing the refs given in @... (which must be %NULL-terminated). Each
|
||||
* #OstreeCollectionRef in @... is followed by a gchar** return address for the
|
||||
* checksum committed for that ref. Return the new repository. */
|
||||
static OstreeRepo *
|
||||
assert_create_remote_va (Fixture *fixture,
|
||||
GFile *repo_dir,
|
||||
va_list args)
|
||||
{
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
g_autoptr(OstreeRepo) repo = ostree_repo_new (repo_dir);
|
||||
ostree_repo_create (repo, OSTREE_REPO_MODE_ARCHIVE_Z2, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
/* Set up the refs from @.... */
|
||||
for (const OstreeCollectionRef *ref = va_arg (args, const OstreeCollectionRef *);
|
||||
ref != NULL;
|
||||
ref = va_arg (args, const OstreeCollectionRef *))
|
||||
{
|
||||
g_autofree gchar *checksum = NULL;
|
||||
g_autoptr(OstreeMutableTree) mtree = NULL;
|
||||
g_autoptr(OstreeRepoFile) repo_file = NULL;
|
||||
gchar **out_checksum = va_arg (args, gchar **);
|
||||
|
||||
mtree = ostree_mutable_tree_new ();
|
||||
ostree_repo_write_dfd_to_mtree (repo, AT_FDCWD, ".", mtree, NULL, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
ostree_repo_write_mtree (repo, mtree, (GFile **) &repo_file, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
ostree_repo_write_commit (repo, NULL /* no parent */, ref->ref_name, ref->ref_name,
|
||||
NULL /* no metadata */, repo_file, &checksum,
|
||||
NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
if (ref->collection_id != NULL)
|
||||
ostree_repo_set_collection_ref_immediate (repo, ref, checksum, NULL, &error);
|
||||
else
|
||||
ostree_repo_set_ref_immediate (repo, NULL, ref->ref_name, checksum, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
if (out_checksum != NULL)
|
||||
*out_checksum = g_steal_pointer (&checksum);
|
||||
}
|
||||
|
||||
/* Update the summary. */
|
||||
ostree_repo_regenerate_summary (repo, NULL /* no metadata */, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
return g_steal_pointer (&repo);
|
||||
}
|
||||
|
||||
static OstreeRepo *
|
||||
assert_create_repo_dir (Fixture *fixture,
|
||||
int repos_dfd,
|
||||
GMount *repos_mount,
|
||||
const OstreeCollectionRef *ref,
|
||||
gchar **out_uri,
|
||||
...) G_GNUC_NULL_TERMINATED;
|
||||
|
||||
/* Create a @ref directory under the given @repos_dfd, or abort. Create a new
|
||||
* repository in it with the refs given in @..., as per assert_create_remote_va().
|
||||
* Return the URI of the repository. */
|
||||
static OstreeRepo *
|
||||
assert_create_repo_dir (Fixture *fixture,
|
||||
int repos_dfd,
|
||||
GMount *repos_mount,
|
||||
const OstreeCollectionRef *ref,
|
||||
gchar **out_uri,
|
||||
...)
|
||||
{
|
||||
glnx_fd_close int ref_dfd = -1;
|
||||
g_autoptr(OstreeRepo) repo = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
va_list args;
|
||||
|
||||
g_autofree gchar *path = g_build_filename (ref->collection_id, ref->ref_name, NULL);
|
||||
glnx_shutil_mkdir_p_at_open (repos_dfd, path, 0700, &ref_dfd, NULL, &error);
|
||||
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS))
|
||||
g_clear_error (&error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
g_autoptr(GFile) mount_root = g_mount_get_root (repos_mount);
|
||||
g_autoptr(GFile) repos_dir = g_file_get_child (mount_root, ".ostree/repos");
|
||||
g_autoptr(GFile) repo_dir = g_file_get_child (repos_dir, path);
|
||||
|
||||
va_start (args, out_uri);
|
||||
repo = assert_create_remote_va (fixture, repo_dir, args);
|
||||
va_end (args);
|
||||
|
||||
*out_uri = g_file_get_uri (repo_dir);
|
||||
|
||||
return g_steal_pointer (&repo);
|
||||
}
|
||||
|
||||
/* Create a @ref symlink under the given @repos_dfd, pointing to
|
||||
* @symlink_target, or abort. */
|
||||
static int
|
||||
assert_create_repo_symlink (int repos_dfd,
|
||||
const OstreeCollectionRef *ref,
|
||||
const gchar *symlink_target_path)
|
||||
{
|
||||
glnx_fd_close int symlink_target_dfd = -1;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
/* The @ref_parent_dir is not necessarily @collection_dir, since @ref may
|
||||
* contain slashes. */
|
||||
g_autofree gchar *path = g_build_filename (ref->collection_id, ref->ref_name, NULL);
|
||||
g_autofree gchar *path_parent = g_path_get_dirname (path);
|
||||
|
||||
glnx_shutil_mkdir_p_at (repos_dfd, path_parent, 0700, NULL, &error);
|
||||
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS))
|
||||
g_clear_error (&error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
if (TEMP_FAILURE_RETRY (symlinkat (symlink_target_path, repos_dfd, path)) != 0)
|
||||
{
|
||||
g_autoptr(GError) error = NULL;
|
||||
glnx_throw_errno_prefix (&error, "symlinkat");
|
||||
g_assert_no_error (error);
|
||||
}
|
||||
|
||||
/* Return a dir FD for the symlink target. */
|
||||
glnx_opendirat (repos_dfd, path, TRUE, &symlink_target_dfd, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
return glnx_steal_fd (&symlink_target_dfd);
|
||||
}
|
||||
|
||||
/* Add configuration for a remote named @remote_name, at @remote_uri, with a
|
||||
* remote collection ID of @collection_id, to the given @repo. */
|
||||
static void
|
||||
assert_create_remote_config (OstreeRepo *repo,
|
||||
const gchar *remote_name,
|
||||
const gchar *remote_uri,
|
||||
const gchar *collection_id)
|
||||
{
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autoptr(GVariant) options = NULL;
|
||||
|
||||
if (collection_id != NULL)
|
||||
options = g_variant_new_parsed ("@a{sv} { 'collection-id': <%s> }",
|
||||
collection_id);
|
||||
|
||||
ostree_repo_remote_add (repo, remote_name, remote_uri, options, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
}
|
||||
|
||||
/* Test resolving the refs against a collection of mock volumes, some of which
|
||||
* are mounted, some of which are removable, some of which contain valid or
|
||||
* invalid repo information on the file system, etc. */
|
||||
static void
|
||||
test_repo_finder_mount_mixed_mounts (Fixture *fixture,
|
||||
gconstpointer test_data)
|
||||
{
|
||||
g_autoptr(OstreeRepoFinderMount) finder = NULL;
|
||||
g_autoptr(GVolumeMonitor) monitor = NULL;
|
||||
g_autoptr(GMainContext) context = NULL;
|
||||
g_autoptr(GAsyncResult) result = NULL;
|
||||
g_autoptr(GPtrArray) results = NULL; /* (element-type OstreeRepoFinderResult) */
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autoptr(GList) mounts = NULL; /* (element-type OstreeMockMount) */
|
||||
g_autoptr(GMount) non_removable_mount = NULL;
|
||||
g_autoptr(GMount) no_repos_mount = NULL;
|
||||
g_autoptr(GMount) repo1_mount = NULL;
|
||||
g_autoptr(GMount) repo2_mount = NULL;
|
||||
g_autoptr(GFile) non_removable_root = NULL;
|
||||
glnx_fd_close int no_repos_repos = -1;
|
||||
glnx_fd_close int repo1_repos = -1;
|
||||
glnx_fd_close int repo2_repos = -1;
|
||||
g_autoptr(OstreeRepo) repo1_repo_a = NULL, repo1_repo_b = NULL;
|
||||
g_autoptr(OstreeRepo) repo2_repo_a = NULL;
|
||||
g_autofree gchar *repo1_repo_a_uri = NULL, *repo1_repo_b_uri = NULL;
|
||||
g_autofree gchar *repo2_repo_a_uri = NULL;
|
||||
g_autofree gchar *repo1_ref0_checksum = NULL, *repo1_ref1_checksum = NULL, *repo1_ref2_checksum = NULL;
|
||||
g_autofree gchar *repo2_ref0_checksum = NULL, *repo2_ref1_checksum = NULL, *repo2_ref2_checksum = NULL;
|
||||
g_autofree gchar *repo1_ref5_checksum = NULL;
|
||||
gsize i;
|
||||
const OstreeCollectionRef ref0 = { "org.example.Collection1", "exampleos/x86_64/ref0" };
|
||||
const OstreeCollectionRef ref1 = { "org.example.Collection1", "exampleos/x86_64/ref1" };
|
||||
const OstreeCollectionRef ref2 = { "org.example.Collection1", "exampleos/x86_64/ref2" };
|
||||
const OstreeCollectionRef ref3 = { "org.example.Collection1", "exampleos/x86_64/ref3" };
|
||||
const OstreeCollectionRef ref4 = { "org.example.UnconfiguredCollection", "exampleos/x86_64/ref4" };
|
||||
const OstreeCollectionRef ref5 = { "org.example.Collection3", "exampleos/x86_64/ref0" };
|
||||
const OstreeCollectionRef * const refs[] = { &ref0, &ref1, &ref2, &ref3, &ref4, &ref5, NULL };
|
||||
|
||||
context = g_main_context_new ();
|
||||
g_main_context_push_thread_default (context);
|
||||
|
||||
/* Build the various mock drives/volumes/mounts, and some repositories with
|
||||
* refs within them. We use "/" under the assumption that it’s on a separate
|
||||
* file system from /tmp, so it’s an example of a symlink pointing outside
|
||||
* its mount point. */
|
||||
non_removable_root = g_file_get_child (fixture->working_dir, "non-removable-mount");
|
||||
non_removable_mount = G_MOUNT (ostree_mock_mount_new ("non-removable", non_removable_root));
|
||||
|
||||
assert_create_repos_dir (fixture, "no-repos-mount", &no_repos_repos, &no_repos_mount);
|
||||
|
||||
assert_create_repos_dir (fixture, "repo1-mount", &repo1_repos, &repo1_mount);
|
||||
repo1_repo_a = assert_create_repo_dir (fixture, repo1_repos, repo1_mount, refs[0], &repo1_repo_a_uri,
|
||||
refs[0], &repo1_ref0_checksum,
|
||||
refs[2], &repo1_ref2_checksum,
|
||||
refs[5], &repo1_ref5_checksum,
|
||||
NULL);
|
||||
repo1_repo_b = assert_create_repo_dir (fixture, repo1_repos, repo1_mount, refs[1], &repo1_repo_b_uri,
|
||||
refs[1], &repo1_ref1_checksum,
|
||||
NULL);
|
||||
assert_create_repo_symlink (repo1_repos, refs[2], "ref0"); /* repo1_repo_a */
|
||||
assert_create_repo_symlink (repo1_repos, refs[5], "../../../org.example.Collection1/exampleos/x86_64/ref0"); /* repo1_repo_a */
|
||||
|
||||
assert_create_repos_dir (fixture, "repo2-mount", &repo2_repos, &repo2_mount);
|
||||
repo2_repo_a = assert_create_repo_dir (fixture, repo2_repos, repo2_mount, refs[0], &repo2_repo_a_uri,
|
||||
refs[0], &repo2_ref0_checksum,
|
||||
refs[1], &repo2_ref1_checksum,
|
||||
refs[2], &repo2_ref2_checksum,
|
||||
refs[3], NULL,
|
||||
NULL);
|
||||
assert_create_repo_symlink (repo2_repos, refs[1], "ref0"); /* repo2_repo_a */
|
||||
assert_create_repo_symlink (repo2_repos, refs[2], "ref1"); /* repo2_repo_b */
|
||||
assert_create_repo_symlink (repo2_repos, refs[3], "/");
|
||||
|
||||
mounts = g_list_prepend (mounts, non_removable_mount);
|
||||
mounts = g_list_prepend (mounts, no_repos_mount);
|
||||
mounts = g_list_prepend (mounts, repo1_mount);
|
||||
mounts = g_list_prepend (mounts, repo2_mount);
|
||||
|
||||
monitor = ostree_mock_volume_monitor_new (mounts, NULL);
|
||||
finder = ostree_repo_finder_mount_new (monitor);
|
||||
|
||||
assert_create_remote_config (fixture->parent_repo, "remote1", "https://nope1", "org.example.Collection1");
|
||||
assert_create_remote_config (fixture->parent_repo, "remote2", "https://nope2", "org.example.Collection2");
|
||||
/* don’t configure org.example.UnconfiguredCollection */
|
||||
assert_create_remote_config (fixture->parent_repo, "remote3", "https://nope3", "org.example.Collection3");
|
||||
|
||||
/* Resolve the refs. */
|
||||
ostree_repo_finder_resolve_async (OSTREE_REPO_FINDER (finder), refs,
|
||||
fixture->parent_repo,
|
||||
NULL, result_cb, &result);
|
||||
|
||||
while (result == NULL)
|
||||
g_main_context_iteration (context, TRUE);
|
||||
|
||||
results = ostree_repo_finder_resolve_finish (OSTREE_REPO_FINDER (finder),
|
||||
result, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert_nonnull (results);
|
||||
g_assert_cmpuint (results->len, ==, 4);
|
||||
|
||||
/* Check that the results are correct: the invalid refs should have been
|
||||
* ignored, and the valid results canonicalised and deduplicated. */
|
||||
for (i = 0; i < results->len; i++)
|
||||
{
|
||||
g_autofree gchar *uri = NULL;
|
||||
const gchar *keyring;
|
||||
const OstreeRepoFinderResult *result = g_ptr_array_index (results, i);
|
||||
|
||||
uri = g_key_file_get_string (result->remote->options, result->remote->group, "url", &error);
|
||||
g_assert_no_error (error);
|
||||
keyring = result->remote->keyring;
|
||||
|
||||
if (g_strcmp0 (uri, repo1_repo_a_uri) == 0 &&
|
||||
g_strcmp0 (keyring, "remote1.trustedkeys.gpg") == 0)
|
||||
{
|
||||
g_assert_cmpuint (g_hash_table_size (result->ref_to_checksum), ==, 2);
|
||||
g_assert_cmpstr (g_hash_table_lookup (result->ref_to_checksum, refs[0]), ==, repo1_ref0_checksum);
|
||||
g_assert_cmpstr (g_hash_table_lookup (result->ref_to_checksum, refs[2]), ==, repo1_ref2_checksum);
|
||||
}
|
||||
else if (g_strcmp0 (uri, repo1_repo_a_uri) == 0 &&
|
||||
g_strcmp0 (keyring, "remote3.trustedkeys.gpg") == 0)
|
||||
{
|
||||
g_assert_cmpuint (g_hash_table_size (result->ref_to_checksum), ==, 1);
|
||||
g_assert_cmpstr (g_hash_table_lookup (result->ref_to_checksum, refs[5]), ==, repo1_ref5_checksum);
|
||||
}
|
||||
else if (g_strcmp0 (uri, repo1_repo_b_uri) == 0 &&
|
||||
g_strcmp0 (keyring, "remote1.trustedkeys.gpg") == 0)
|
||||
{
|
||||
g_assert_cmpuint (g_hash_table_size (result->ref_to_checksum), ==, 1);
|
||||
g_assert_cmpstr (g_hash_table_lookup (result->ref_to_checksum, refs[1]), ==, repo1_ref1_checksum);
|
||||
}
|
||||
else if (g_strcmp0 (uri, repo2_repo_a_uri) == 0 &&
|
||||
g_strcmp0 (keyring, "remote1.trustedkeys.gpg") == 0)
|
||||
{
|
||||
g_assert_cmpuint (g_hash_table_size (result->ref_to_checksum), ==, 3);
|
||||
g_assert_cmpstr (g_hash_table_lookup (result->ref_to_checksum, refs[0]), ==, repo2_ref0_checksum);
|
||||
g_assert_cmpstr (g_hash_table_lookup (result->ref_to_checksum, refs[1]), ==, repo2_ref1_checksum);
|
||||
g_assert_cmpstr (g_hash_table_lookup (result->ref_to_checksum, refs[2]), ==, repo2_ref2_checksum);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_test_message ("Unknown result ‘%s’ with keyring ‘%s’.",
|
||||
result->remote->name, result->remote->keyring);
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
g_main_context_pop_thread_default (context);
|
||||
}
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
setlocale (LC_ALL, "");
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
|
||||
g_test_add_func ("/repo-finder-mount/init", test_repo_finder_mount_init);
|
||||
g_test_add ("/repo-finder-mount/no-mounts", Fixture, NULL, setup,
|
||||
test_repo_finder_mount_no_mounts, teardown);
|
||||
g_test_add ("/repo-finder-mount/mixed-mounts", Fixture, NULL, setup,
|
||||
test_repo_finder_mount_mixed_mounts, teardown);
|
||||
|
||||
return g_test_run();
|
||||
}
|
||||
Executable
+94
@@ -0,0 +1,94 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright © 2017 Endless Mobile, Inc.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# Authors:
|
||||
# - Philip Withnall <withnall@endlessm.com>
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
. $(dirname $0)/libtest.sh
|
||||
|
||||
echo "1..2"
|
||||
|
||||
cd ${test_tmpdir}
|
||||
mkdir repo
|
||||
ostree_repo_init repo
|
||||
|
||||
mkdir -p tree/root
|
||||
touch tree/root/a
|
||||
|
||||
# Add a few commits
|
||||
seq 5 | while read i; do
|
||||
echo a >> tree/root/a
|
||||
${CMD_PREFIX} ostree --repo=repo commit --branch=test-$i -m test -s test tree
|
||||
done
|
||||
|
||||
# Generate a plain summary file.
|
||||
${CMD_PREFIX} ostree --repo=repo summary --update
|
||||
|
||||
# Generate a signed summary file.
|
||||
${CMD_PREFIX} ostree --repo=repo summary --update --gpg-homedir=${TEST_GPG_KEYHOME} --gpg-sign=${TEST_GPG_KEYID_1}
|
||||
|
||||
# Try various ways of adding additional data.
|
||||
${CMD_PREFIX} ostree --repo=repo summary --update --add-metadata key="'value'" --add-metadata=key2=true
|
||||
${CMD_PREFIX} ostree --repo=repo summary --update -m some-int='@t 123'
|
||||
${CMD_PREFIX} ostree --repo=repo summary --update --add-metadata=map='@a{sv} {}'
|
||||
|
||||
# Check the additional metadata turns up in the output.
|
||||
${CMD_PREFIX} ostree --repo=repo summary --view > summary
|
||||
assert_file_has_content summary "^map: {}$"
|
||||
|
||||
echo "ok 1 update summary"
|
||||
|
||||
# Test again, but with collections enabled in the repository (if supported).
|
||||
if ! ostree --version | grep -q -e '- experimental'; then
|
||||
echo "ok 2 # skip No experimental API is compiled in"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
cd ${test_tmpdir}
|
||||
rm -rf repo
|
||||
ostree_repo_init repo --collection-id org.example.Collection1
|
||||
|
||||
mkdir -p tree/root
|
||||
touch tree/root/a
|
||||
|
||||
# Add a few commits
|
||||
seq 5 | while read i; do
|
||||
echo a >> tree/root/a
|
||||
${CMD_PREFIX} ostree --repo=repo commit --branch=test-$i -m test -s test tree
|
||||
${CMD_PREFIX} ostree --repo=repo refs --collections --create=org.example.Collection2:test-$i test-$i
|
||||
done
|
||||
|
||||
# Generate a plain summary file.
|
||||
${CMD_PREFIX} ostree --repo=repo summary --update
|
||||
|
||||
# Generate a signed summary file.
|
||||
${CMD_PREFIX} ostree --repo=repo summary --update --gpg-homedir=${TEST_GPG_KEYHOME} --gpg-sign=${TEST_GPG_KEYID_1}
|
||||
|
||||
# Try various ways of adding additional data.
|
||||
${CMD_PREFIX} ostree --repo=repo summary --update --add-metadata key="'value'" --add-metadata=key2=true
|
||||
${CMD_PREFIX} ostree --repo=repo summary --update -m some-int='@t 123'
|
||||
${CMD_PREFIX} ostree --repo=repo summary --update --add-metadata=map='@a{sv} {}'
|
||||
|
||||
# Check the additional metadata turns up in the output.
|
||||
${CMD_PREFIX} ostree --repo=repo summary --view > summary
|
||||
assert_file_has_content summary "^map: {}$"
|
||||
|
||||
echo "ok 2 update summary with collections"
|
||||
@@ -127,6 +127,8 @@ if [ "${BASH_SOURCE[0]}" = "${0}" ]; then
|
||||
. $(dirname $0)/libtest.sh
|
||||
unshare -m true || \
|
||||
skip "this test needs to set up mount namespaces, rerun as root"
|
||||
[ -f /bin/busybox ] || \
|
||||
skip "this test needs busybox"
|
||||
|
||||
echo "1..3"
|
||||
test_that_prepare_root_sets_sysroot_up_correctly_with_initrd
|
||||
|
||||
@@ -22,7 +22,11 @@ set -xeuo pipefail
|
||||
echo '1..3'
|
||||
|
||||
released_syms=${G_TEST_SRCDIR}/src/libostree/libostree-released.sym
|
||||
devel_syms=${G_TEST_SRCDIR}/src/libostree/libostree-devel.sym
|
||||
if echo "$OSTREE_FEATURES" | grep --quiet --no-messages "devel"; then
|
||||
devel_syms=${G_TEST_SRCDIR}/src/libostree/libostree-devel.sym
|
||||
else
|
||||
devel_syms=
|
||||
fi
|
||||
if echo "$OSTREE_FEATURES" | grep --quiet --no-messages "experimental"; then
|
||||
experimental_sym="${G_TEST_SRCDIR}/src/libostree/libostree-experimental.sym"
|
||||
experimental_sections="${G_TEST_SRCDIR}/apidoc/ostree-experimental-sections.txt"
|
||||
@@ -48,7 +52,7 @@ echo 'ok documented symbols'
|
||||
|
||||
# ONLY update this checksum in release commits!
|
||||
cat > released-sha256.txt <<EOF
|
||||
42f98d8816acbe22e925d18bf76ea2c6f7e12ee5d7a381979e6ed07bb6a1f755 ${released_syms}
|
||||
d3f3d564e4679d603220da0cea940867fde28622857d088a8287db730bcc8001 ${released_syms}
|
||||
EOF
|
||||
sha256sum -c released-sha256.txt
|
||||
|
||||
|
||||
Reference in new issue
Block a user