5cb1fa5460
Having to prepare RPMs in advance separately from the tests that use them severely limits our ability to test various cases and to iterate quickly when creating tests. Add a new `build_rpm` function which can basically build the RPM on the fly and update the yum repo afterwards. It makes it trivial to test things like package updates: build_rpm foo 1.0 1 <stuff> build_rpm foo 1.0 2 <stuff> The RPMs are all created inside the temporary test directory and thus cleaned up on exit. I'm doing this in a separate commit because it's the most important diff of the transition and might be easy to lose in the larger diff where we move all the tests to make use of this. Closes: #854 Approved by: cgwalters
453 lines
13 KiB
Bash
453 lines
13 KiB
Bash
# Source library for shell script tests
|
|
#
|
|
# 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.
|
|
|
|
# Have we already been sourced?
|
|
if test -n "${LIBTEST_SH:-}"; then
|
|
# would be good to know when it happens
|
|
echo "INFO: Skipping subsequent sourcing of libtest.sh"
|
|
return
|
|
fi
|
|
LIBTEST_SH=1
|
|
|
|
self="$(realpath $0)"
|
|
if test -z "${SRCDIR:-}"; then
|
|
SRCDIR=${topsrcdir}/tests
|
|
fi
|
|
. ${SRCDIR}/common/libtest-core.sh
|
|
|
|
for bin in jq; do
|
|
if ! command -v $bin >/dev/null; then
|
|
(echo ${bin} is required to execute tests 1>&2; exit 1)
|
|
fi
|
|
done
|
|
|
|
_cleanup_tmpdir () {
|
|
if test -z "${TEST_SKIP_CLEANUP:-}"; then
|
|
if test -f ${test_tmpdir}/.test; then
|
|
rm ${test_tmpdir} -rf
|
|
fi
|
|
else
|
|
echo "Skipping cleanup of ${test_tmpdir}"
|
|
fi
|
|
}
|
|
|
|
# Create a tmpdir if we're running as a local test (i.e. through `make check`)
|
|
# or as a `vmcheck` test, which also needs some scratch space on the host.
|
|
if ( test -n "${UNINSTALLEDTESTS:-}" || test -n "${VMTESTS:-}" ) && ! test -f $PWD/.test; then
|
|
test_tmpdir=$(mktemp -d test.XXXXXX)
|
|
touch ${test_tmpdir}/.test
|
|
trap _cleanup_tmpdir EXIT
|
|
cd ${test_tmpdir}
|
|
fi
|
|
if test -n "${UNINSTALLEDTESTS:-}"; then
|
|
export PATH=${builddir}:${PATH}
|
|
fi
|
|
|
|
test_tmpdir=$(pwd)
|
|
echo "Using tmpdir ${test_tmpdir}"
|
|
|
|
export G_DEBUG=fatal-warnings
|
|
|
|
# Don't flag deployments as immutable so that test harnesses can
|
|
# easily clean up.
|
|
export OSTREE_SYSROOT_DEBUG=mutable-deployments
|
|
|
|
# See comment in ot-builtin-commit.c and https://github.com/ostreedev/ostree/issues/758
|
|
# Also keep this in sync with the bits in libostreetest.c
|
|
case $(stat -f --printf '%T' /) in
|
|
overlayfs)
|
|
echo "overlayfs found; enabling OSTREE_NO_XATTRS"
|
|
ostree --version
|
|
export OSTREE_SYSROOT_DEBUG="${OSTREE_SYSROOT_DEBUG},no-xattrs"
|
|
export OSTREE_NO_XATTRS=1 ;;
|
|
*) echo "Not using overlayfs" ;;
|
|
esac
|
|
|
|
export TEST_GPG_KEYID="472CDAFA"
|
|
|
|
# GPG when creating signatures demands a writable
|
|
# homedir in order to create lockfiles. Work around
|
|
# this by copying locally.
|
|
echo "Copying gpghome to ${test_tmpdir}"
|
|
cp -a "${SRCDIR}/gpghome" ${test_tmpdir}
|
|
chmod -R u+w "${test_tmpdir}"
|
|
export TEST_GPG_KEYHOME=${test_tmpdir}/gpghome
|
|
export OSTREE_GPG_HOME=${test_tmpdir}/gpghome/trusted
|
|
|
|
if test -n "${OT_TESTS_DEBUG:-}"; then
|
|
set -x
|
|
fi
|
|
|
|
if test -n "${OT_TESTS_VALGRIND:-}"; then
|
|
CMD_PREFIX="env G_SLICE=always-malloc valgrind -q --leak-check=full --num-callers=30 --suppressions=${SRCDIR}/ostree-valgrind.supp"
|
|
fi
|
|
|
|
# A wrapper which also possibly disables xattrs for CI testing
|
|
ostree_repo_init() {
|
|
repo=$1
|
|
shift
|
|
${CMD_PREFIX} ostree --repo=${repo} init "$@"
|
|
if test -n "${OSTREE_NO_XATTRS:-}"; then
|
|
echo -e 'disable-xattrs=true\n' >> ${repo}/config
|
|
fi
|
|
}
|
|
|
|
setup_test_repository () {
|
|
mode=$1
|
|
shift
|
|
|
|
oldpwd=`pwd`
|
|
|
|
cd ${test_tmpdir}
|
|
if test -n "${mode}"; then
|
|
ostree_repo_init repo --mode=${mode}
|
|
else
|
|
ostree_repo_init repo
|
|
fi
|
|
ot_repo="--repo=$(pwd)/repo"
|
|
export OSTREE="${CMD_PREFIX} ostree ${ot_repo}"
|
|
|
|
cd ${test_tmpdir}/files
|
|
$OSTREE commit -b test2 -s "Test Commit 1" -m "Commit body first"
|
|
|
|
mkdir baz
|
|
echo moo > baz/cow
|
|
echo alien > baz/saucer
|
|
mkdir baz/deeper
|
|
echo hi > baz/deeper/ohyeah
|
|
ln -s nonexistent baz/alink
|
|
mkdir baz/another/
|
|
echo x > baz/another/y
|
|
|
|
cd ${test_tmpdir}/files
|
|
$OSTREE commit -b test2 -s "Test Commit 2" -m "Commit body second"
|
|
$OSTREE fsck -q
|
|
|
|
cd $oldpwd
|
|
}
|
|
|
|
run_temp_webserver() {
|
|
env PYTHONUNBUFFERED=1 setsid python -m SimpleHTTPServer 0 >${test_tmpdir}/httpd-output &
|
|
for x in $(seq 50); do
|
|
sed -e 's,Serving HTTP on 0.0.0.0 port \([0-9]*\) \.\.\.,\1,' < ${test_tmpdir}/httpd-output > ${test_tmpdir}/httpd-port
|
|
if ! cmp ${test_tmpdir}/httpd-output ${test_tmpdir}/httpd-port 1>/dev/null; then
|
|
break
|
|
fi
|
|
sleep 0.1
|
|
done
|
|
port=$(cat ${test_tmpdir}/httpd-port)
|
|
echo "http://127.0.0.1:${port}" > ${test_tmpdir}/httpd-address
|
|
}
|
|
|
|
setup_fake_remote_repo1() {
|
|
mode=$1
|
|
args=$2
|
|
shift
|
|
oldpwd=`pwd`
|
|
mkdir ostree-srv
|
|
cd ostree-srv
|
|
ostree_repo_init gnomerepo --mode=$mode
|
|
mkdir gnomerepo-files
|
|
cd gnomerepo-files
|
|
echo first > firstfile
|
|
mkdir baz
|
|
echo moo > baz/cow
|
|
echo alien > baz/saucer
|
|
${CMD_PREFIX} ostree --repo=${test_tmpdir}/ostree-srv/gnomerepo commit --add-metadata-string version=3.0 -b main -s "A remote commit" -m "Some Commit body"
|
|
mkdir baz/deeper
|
|
${CMD_PREFIX} ostree --repo=${test_tmpdir}/ostree-srv/gnomerepo commit --add-metadata-string version=3.1 -b main -s "Add deeper"
|
|
echo hi > baz/deeper/ohyeah
|
|
mkdir baz/another/
|
|
echo x > baz/another/y
|
|
${CMD_PREFIX} ostree --repo=${test_tmpdir}/ostree-srv/gnomerepo commit --add-metadata-string version=3.2 -b main -s "The rest"
|
|
cd ..
|
|
rm -rf gnomerepo-files
|
|
|
|
cd ${test_tmpdir}
|
|
mkdir ${test_tmpdir}/httpd
|
|
cd httpd
|
|
ln -s ${test_tmpdir}/ostree-srv ostree
|
|
run_temp_webserver
|
|
cd ${oldpwd}
|
|
|
|
export OSTREE="ostree --repo=repo"
|
|
}
|
|
|
|
setup_os_boot_syslinux() {
|
|
# Stub syslinux configuration
|
|
mkdir -p sysroot/boot/loader.0
|
|
ln -s loader.0 sysroot/boot/loader
|
|
touch sysroot/boot/loader/syslinux.cfg
|
|
# And a compatibility symlink
|
|
mkdir -p sysroot/boot/syslinux
|
|
ln -s ../loader/syslinux.cfg sysroot/boot/syslinux/syslinux.cfg
|
|
}
|
|
|
|
setup_os_boot_uboot() {
|
|
# Stub U-Boot configuration
|
|
mkdir -p sysroot/boot/loader.0
|
|
ln -s loader.0 sysroot/boot/loader
|
|
touch sysroot/boot/loader/uEnv.txt
|
|
# And a compatibility symlink
|
|
ln -s loader/uEnv.txt sysroot/boot/uEnv.txt
|
|
}
|
|
|
|
setup_os_repository () {
|
|
mode=$1
|
|
bootmode=$2
|
|
shift
|
|
|
|
oldpwd=`pwd`
|
|
|
|
cd ${test_tmpdir}
|
|
mkdir testos-repo
|
|
if test -n "$mode"; then
|
|
ostree_repo_init testos-repo --mode=${mode}
|
|
else
|
|
ostree_repo_init testos-repo
|
|
fi
|
|
|
|
cd ${test_tmpdir}
|
|
mkdir osdata
|
|
cd osdata
|
|
mkdir -p boot usr/bin usr/lib/modules/3.6.0 usr/share usr/etc
|
|
echo "a kernel" > boot/vmlinuz-3.6.0
|
|
echo "an initramfs" > boot/initramfs-3.6.0
|
|
bootcsum=$(cat boot/vmlinuz-3.6.0 boot/initramfs-3.6.0 | sha256sum | cut -f 1 -d ' ')
|
|
export bootcsum
|
|
mv boot/vmlinuz-3.6.0 boot/vmlinuz-3.6.0-${bootcsum}
|
|
mv boot/initramfs-3.6.0 boot/initramfs-3.6.0-${bootcsum}
|
|
|
|
echo "an executable" > usr/bin/sh
|
|
echo "some shared data" > usr/share/langs.txt
|
|
echo "a library" > usr/lib/libfoo.so.0
|
|
ln -s usr/bin bin
|
|
cat > usr/etc/os-release <<EOF
|
|
NAME=TestOS
|
|
VERSION=42
|
|
ID=testos
|
|
VERSION_ID=42
|
|
PRETTY_NAME="TestOS 42"
|
|
EOF
|
|
echo "a config file" > usr/etc/aconfigfile
|
|
mkdir -p usr/etc/NetworkManager
|
|
echo "a default daemon file" > usr/etc/NetworkManager/nm.conf
|
|
mkdir -p usr/etc/testdirectory
|
|
echo "a default daemon file" > usr/etc/testdirectory/test
|
|
|
|
ostree --repo=${test_tmpdir}/testos-repo commit --add-metadata-string version=1.0.9 -b testos/buildmaster/x86_64-runtime -s "Build"
|
|
|
|
# Ensure these commits have distinct second timestamps
|
|
sleep 2
|
|
echo "a new executable" > usr/bin/sh
|
|
ostree --repo=${test_tmpdir}/testos-repo commit --add-metadata-string version=1.0.10 -b testos/buildmaster/x86_64-runtime -s "Build"
|
|
|
|
cd ${test_tmpdir}
|
|
cp -a osdata osdata-devel
|
|
cd osdata-devel
|
|
mkdir -p usr/include
|
|
echo "a development header" > usr/include/foo.h
|
|
ostree --repo=${test_tmpdir}/testos-repo commit --add-metadata-string version=1.0.9 -b testos/buildmaster/x86_64-devel -s "Build"
|
|
|
|
ostree --repo=${test_tmpdir}/testos-repo fsck -q
|
|
|
|
cd ${test_tmpdir}
|
|
# sysroot dir already made by setup-session.sh
|
|
ostree admin --sysroot=sysroot init-fs sysroot
|
|
if test -n "${OSTREE_NO_XATTRS:-}"; then
|
|
echo -e 'disable-xattrs=true\n' >> sysroot/ostree/repo/config
|
|
fi
|
|
ostree admin --sysroot=sysroot os-init testos
|
|
|
|
case $bootmode in
|
|
"syslinux")
|
|
setup_os_boot_syslinux
|
|
;;
|
|
"uboot")
|
|
setup_os_boot_uboot
|
|
;;
|
|
esac
|
|
|
|
cd ${test_tmpdir}
|
|
mkdir ${test_tmpdir}/httpd
|
|
cd httpd
|
|
ln -s ${test_tmpdir} ostree
|
|
run_temp_webserver
|
|
cd ${oldpwd}
|
|
}
|
|
|
|
os_repository_new_commit ()
|
|
{
|
|
boot_checksum_iteration=$1
|
|
content_iteration=$2
|
|
echo "BOOT ITERATION: $boot_checksum_iteration"
|
|
if test -z "$boot_checksum_iteration"; then
|
|
boot_checksum_iteration=0
|
|
fi
|
|
if test -z "$content_iteration"; then
|
|
content_iteration=0
|
|
fi
|
|
cd ${test_tmpdir}/osdata
|
|
rm boot/*
|
|
echo "new: a kernel ${boot_checksum_iteration}" > boot/vmlinuz-3.6.0
|
|
echo "new: an initramfs ${boot_checksum_iteration}" > boot/initramfs-3.6.0
|
|
bootcsum=$(cat boot/vmlinuz-3.6.0 boot/initramfs-3.6.0 | sha256sum | cut -f 1 -d ' ')
|
|
export bootcsum
|
|
mv boot/vmlinuz-3.6.0 boot/vmlinuz-3.6.0-${bootcsum}
|
|
mv boot/initramfs-3.6.0 boot/initramfs-3.6.0-${bootcsum}
|
|
|
|
echo "a new default config file" > usr/etc/a-new-default-config-file
|
|
mkdir -p usr/etc/new-default-dir
|
|
echo "a new default dir and file" > usr/etc/new-default-dir/moo
|
|
|
|
echo "content iteration ${content_iteration}" > usr/bin/content-iteration
|
|
|
|
version=$(date "+%Y%m%d.${content_iteration}")
|
|
echo "version: $version"
|
|
|
|
ostree --repo=${test_tmpdir}/testos-repo commit --add-metadata-string "version=${version}" -b testos/buildmaster/x86_64-runtime -s "Build"
|
|
cd ${test_tmpdir}
|
|
}
|
|
|
|
check_root_test ()
|
|
{
|
|
if test "$(id -u)" != "0"; then
|
|
skip "This test requires uid 0"
|
|
fi
|
|
if ! capsh --print | grep -q 'Bounding set.*[^a-z]cap_sys_admin'; then
|
|
skip "No CAP_SYS_ADMIN in bounding set"
|
|
fi
|
|
}
|
|
|
|
ensure_dbus ()
|
|
{
|
|
if test -z "$RPMOSTREE_USE_SESSION_BUS"; then
|
|
exec "$topsrcdir/tests/utils/setup-session.sh" "$self"
|
|
fi
|
|
}
|
|
|
|
assert_status_file_jq() {
|
|
status_file=$1; shift
|
|
for expression in "$@"; do
|
|
if ! jq -e "${expression}" >/dev/null < $status_file; then
|
|
jq . < $status_file | sed -e 's/^/# /' >&2
|
|
echo 1>&2 "${expression} failed to match in $status_file"
|
|
exit 1
|
|
fi
|
|
done
|
|
}
|
|
|
|
assert_status_jq() {
|
|
rpm-ostree status --json > status.json
|
|
assert_status_file_jq status.json "$@"
|
|
}
|
|
|
|
# builds a new RPM and adds it to the testdir's repo
|
|
# $1 - name
|
|
# $2+ - optional, treated as directive/value pairs
|
|
build_rpm() {
|
|
local name=$1; shift
|
|
local version=1.0
|
|
local release=1
|
|
local arch=x86_64
|
|
|
|
mkdir -p $test_tmpdir/yumrepo/{specs,packages}
|
|
local spec=$test_tmpdir/yumrepo/specs/$name.spec
|
|
|
|
# write out the header
|
|
cat > $spec << EOF
|
|
Name: $name
|
|
Summary: %{name}
|
|
License: GPLv2+
|
|
EOF
|
|
|
|
local build= install= files= pretrans= pre= post= posttrans=
|
|
while [ $# -ne 0 ]; do
|
|
local section=$1; shift
|
|
local arg=$1; shift
|
|
case $section in
|
|
requires)
|
|
echo "Requires: $arg" >> $spec;;
|
|
provides)
|
|
echo "Provides: $arg" >> $spec;;
|
|
conflicts)
|
|
echo "Conflicts: $arg" >> $spec;;
|
|
version|release|arch|build|install|files|pretrans|pre|post|posttrans)
|
|
declare $section="$arg";;
|
|
*)
|
|
assert_not_reached "unhandled section $section";;
|
|
esac
|
|
done
|
|
|
|
cat >> $spec << EOF
|
|
Version: $version
|
|
Release: $release
|
|
BuildArch: $arch
|
|
|
|
%description
|
|
%{summary}
|
|
|
|
# by default, we create a /usr/bin/$name script which just outputs $name
|
|
%build
|
|
echo -e "#!/bin/sh\necho $name" > $name
|
|
chmod a+x $name
|
|
$build
|
|
|
|
${pretrans:+%pretrans}
|
|
$pretrans
|
|
|
|
${pre:+%pre}
|
|
$pre
|
|
|
|
${post:+%post}
|
|
$post
|
|
|
|
${posttrans:+%posttrans}
|
|
$posttrans
|
|
|
|
%install
|
|
mkdir -p %{buildroot}/usr/bin
|
|
install $name %{buildroot}/usr/bin
|
|
$install
|
|
|
|
%clean
|
|
rm -rf %{buildroot}
|
|
|
|
%files
|
|
/usr/bin/$name
|
|
$files
|
|
EOF
|
|
(cd $test_tmpdir/yumrepo/specs &&
|
|
rpmbuild -ba $name.spec \
|
|
--define "_sourcedir $PWD" \
|
|
--define "_specdir $PWD" \
|
|
--define "_builddir $PWD/.build" \
|
|
--define "_srcrpmdir $PWD" \
|
|
--define "_rpmdir $test_tmpdir/yumrepo/packages" \
|
|
--define "_buildrootdir $PWD")
|
|
(cd yumrepo && createrepo_c --no-database .)
|
|
if test -n yumrepo.repo; then
|
|
cat > yumrepo.repo << EOF
|
|
[test-repo]
|
|
name=test-repo
|
|
baseurl=file:///$PWD/yumrepo
|
|
EOF
|
|
fi
|
|
}
|