2014-07-16 17:02:45 +04:00
# 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.
2016-02-26 20:52:42 +03:00
# 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
2016-06-06 19:08:29 +03:00
self = " $( realpath $0 ) "
2017-05-19 20:24:42 +03:00
if test -z " ${ SRCDIR :- } " ; then
SRCDIR = ${ topsrcdir } /tests
fi
. ${ SRCDIR } /common/libtest-core.sh
2016-06-06 19:08:29 +03:00
2017-01-17 17:12:26 +03:00
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
2016-02-10 13:42:57 +03:00
_cleanup_tmpdir ( ) {
2016-12-03 02:07:08 +03:00
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 } "
2016-02-10 13:42:57 +03:00
fi
}
2016-02-26 19:12:11 +03:00
2016-06-21 19:37:02 +03:00
# 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
2016-02-10 13:42:57 +03:00
test_tmpdir = $( mktemp -d test.XXXXXX)
touch ${ test_tmpdir } /.test
trap _cleanup_tmpdir EXIT
cd ${ test_tmpdir }
2016-12-03 02:07:08 +03:00
fi
if test -n " ${ UNINSTALLEDTESTS :- } " ; then
export PATH = ${ builddir } :${ PATH }
2016-02-26 19:12:11 +03:00
fi
2014-07-16 17:02:45 +04:00
test_tmpdir = $( pwd )
2017-01-11 23:24:30 +03:00
echo " Using tmpdir ${ test_tmpdir } "
2014-07-16 17:02:45 +04:00
export G_DEBUG = fatal-warnings
2016-02-19 20:34:36 +03:00
# Don't flag deployments as immutable so that test harnesses can
# easily clean up.
export OSTREE_SYSROOT_DEBUG = mutable-deployments
2017-03-25 19:01:03 +03:00
# 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
2014-07-16 17:02:45 +04:00
export TEST_GPG_KEYID = "472CDAFA"
2016-12-22 20:39:28 +03:00
# 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
2014-07-16 17:02:45 +04:00
2016-02-10 13:42:57 +03:00
if test -n " ${ OT_TESTS_DEBUG :- } " ; then
2014-07-16 17:02:45 +04:00
set -x
fi
2016-02-10 13:42:57 +03:00
if test -n " ${ OT_TESTS_VALGRIND :- } " ; then
2014-07-16 17:02:45 +04:00
CMD_PREFIX = " env G_SLICE=always-malloc valgrind -q --leak-check=full --num-callers=30 --suppressions= ${ SRCDIR } /ostree-valgrind.supp "
fi
2017-03-25 19:01:03 +03:00
# 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
}
2014-07-16 17:02:45 +04:00
setup_test_repository ( ) {
mode = $1
shift
oldpwd = ` pwd `
cd ${ test_tmpdir }
2017-03-25 19:01:03 +03:00
if test -n " ${ mode } " ; then
ostree_repo_init repo --mode= ${ mode }
2014-07-16 17:02:45 +04:00
else
2017-03-25 19:01:03 +03:00
ostree_repo_init repo
2014-07-16 17:02:45 +04:00
fi
2017-03-25 19:01:03 +03:00
ot_repo = " --repo= $( pwd ) /repo "
export OSTREE = " ${ CMD_PREFIX } ostree ${ ot_repo } "
2014-07-16 17:02:45 +04:00
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
}
2017-03-16 04:53:31 +03:00
run_temp_webserver( ) {
env PYTHONUNBUFFERED = 1 setsid python -m SimpleHTTPServer 0 >${ test_tmpdir } /httpd-output &
for x in $( seq 50) ; do
2017-10-02 20:03:31 +03:00
if test -e ${ test_tmpdir } /httpd-output; then
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
2017-03-16 04:53:31 +03:00
fi
sleep 0.1
done
port = $( cat ${ test_tmpdir } /httpd-port)
echo " http://127.0.0.1: ${ port } " > ${ test_tmpdir } /httpd-address
}
2014-07-16 17:02:45 +04:00
setup_fake_remote_repo1( ) {
mode = $1
args = $2
shift
oldpwd = ` pwd `
mkdir ostree-srv
cd ostree-srv
2017-03-25 19:01:03 +03:00
ostree_repo_init gnomerepo --mode= $mode
2014-07-16 17:02:45 +04:00
mkdir gnomerepo-files
cd gnomerepo-files
echo first > firstfile
mkdir baz
echo moo > baz/cow
echo alien > baz/saucer
2014-10-28 07:47:01 +03:00
${ 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"
2014-07-16 17:02:45 +04:00
mkdir baz/deeper
2014-10-28 07:47:01 +03:00
${ CMD_PREFIX } ostree --repo= ${ test_tmpdir } /ostree-srv/gnomerepo commit --add-metadata-string version = 3.1 -b main -s "Add deeper"
2014-07-16 17:02:45 +04:00
echo hi > baz/deeper/ohyeah
mkdir baz/another/
echo x > baz/another/y
2014-10-28 07:47:01 +03:00
${ CMD_PREFIX } ostree --repo= ${ test_tmpdir } /ostree-srv/gnomerepo commit --add-metadata-string version = 3.2 -b main -s "The rest"
2014-07-16 17:02:45 +04:00
cd ..
rm -rf gnomerepo-files
cd ${ test_tmpdir }
mkdir ${ test_tmpdir } /httpd
cd httpd
ln -s ${ test_tmpdir } /ostree-srv ostree
2017-03-16 04:53:31 +03:00
run_temp_webserver
2014-07-16 17:02:45 +04:00
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
2017-03-25 19:01:03 +03:00
ostree_repo_init testos-repo --mode= ${ mode }
2014-07-16 17:02:45 +04:00
else
2017-03-25 19:01:03 +03:00
ostree_repo_init testos-repo
2014-07-16 17:02:45 +04:00
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 }
2017-05-19 20:24:42 +03:00
2014-07-16 17:02:45 +04:00
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
2014-10-28 07:47:01 +03:00
ostree --repo= ${ test_tmpdir } /testos-repo commit --add-metadata-string version = 1.0.9 -b testos/buildmaster/x86_64-runtime -s "Build"
2017-05-19 20:24:42 +03:00
2014-07-16 17:02:45 +04:00
# Ensure these commits have distinct second timestamps
sleep 2
echo "a new executable" > usr/bin/sh
2014-10-28 07:47:01 +03:00
ostree --repo= ${ test_tmpdir } /testos-repo commit --add-metadata-string version = 1.0.10 -b testos/buildmaster/x86_64-runtime -s "Build"
2014-07-16 17:02:45 +04:00
cd ${ test_tmpdir }
cp -a osdata osdata-devel
cd osdata-devel
mkdir -p usr/include
echo "a development header" > usr/include/foo.h
2014-10-28 07:47:01 +03:00
ostree --repo= ${ test_tmpdir } /testos-repo commit --add-metadata-string version = 1.0.9 -b testos/buildmaster/x86_64-devel -s "Build"
2014-07-16 17:02:45 +04:00
ostree --repo= ${ test_tmpdir } /testos-repo fsck -q
cd ${ test_tmpdir }
2015-09-01 21:46:32 +03:00
# sysroot dir already made by setup-session.sh
2014-07-16 17:02:45 +04:00
ostree admin --sysroot= sysroot init-fs sysroot
2017-05-09 00:59:14 +03:00
if test -n " ${ OSTREE_NO_XATTRS :- } " ; then
echo -e 'disable-xattrs=true\n' >> sysroot/ostree/repo/config
fi
2014-07-16 17:02:45 +04:00
ostree admin --sysroot= sysroot os-init testos
case $bootmode in
"syslinux" )
setup_os_boot_syslinux
; ;
"uboot" )
setup_os_boot_uboot
; ;
esac
2017-05-19 20:24:42 +03:00
2014-07-16 17:02:45 +04:00
cd ${ test_tmpdir }
mkdir ${ test_tmpdir } /httpd
cd httpd
ln -s ${ test_tmpdir } ostree
2017-03-16 04:53:31 +03:00
run_temp_webserver
2014-07-16 17:02:45 +04:00
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
2014-10-28 07:47:01 +03:00
version = $( date " +%Y%m%d. ${ content_iteration } " )
2016-12-21 18:40:42 +03:00
echo " version: $version "
2014-10-28 07:47:01 +03:00
ostree --repo= ${ test_tmpdir } /testos-repo commit --add-metadata-string " version= ${ version } " -b testos/buildmaster/x86_64-runtime -s "Build"
2014-07-16 17:02:45 +04:00
cd ${ test_tmpdir }
}
2015-04-01 14:25:36 +03:00
check_root_test ( )
{
if test " $( id -u) " != "0" ; then
2016-10-28 23:43:16 +03:00
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"
2016-06-06 19:08:29 +03:00
fi
}
ensure_dbus ( )
{
if test -z " $RPMOSTREE_USE_SESSION_BUS " ; then
2016-06-06 19:46:48 +03:00
exec " $topsrcdir /tests/utils/setup-session.sh " " $self "
2015-04-01 14:25:36 +03:00
fi
}
2017-01-27 07:31:53 +03:00
2017-09-21 23:59:28 +03:00
# https://github.com/ostreedev/ostree/commit/47b4dd1b38e422254afa67756873957c25aeab6d
# Unfortunately, introspection uses dlopen(), which doesn't quite
# work when the DSO is compiled with ASAN but the outer executable
# isn't.
skip_one_with_asan ( ) {
if test -n " ${ BUILDOPT_ASAN :- } " ; then
echo "ok # SKIP - built with ASAN"
return 0
else
return 1
fi
}
2017-02-08 01:49:20 +03:00
assert_status_file_jq( ) {
status_file = $1 ; shift
2017-01-27 07:31:53 +03:00
for expression in " $@ " ; do
2017-02-08 01:49:20 +03:00
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 "
2017-01-27 07:31:53 +03:00
exit 1
fi
done
}
2017-02-08 01:49:20 +03:00
assert_status_jq( ) {
rpm-ostree status --json > status.json
assert_status_file_jq status.json " $@ "
}
2017-06-29 17:06:36 +03:00
# 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
2017-07-13 03:50:08 +03:00
local build = install = files = pretrans = pre = post = posttrans = post_args =
2017-07-07 17:45:10 +03:00
local transfiletriggerin = transfiletriggerin_patterns =
local transfiletriggerin2 = transfiletriggerin2_patterns =
local transfiletriggerun = transfiletriggerun_patterns =
2017-06-29 17:06:36 +03:00
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 ; ;
2017-07-13 03:50:08 +03:00
post_args)
post_args = " $arg " ; ;
2017-06-29 17:06:36 +03:00
version| release| arch| build| install| files| pretrans| pre| post| posttrans)
declare $section = " $arg " ; ;
2017-07-07 17:45:10 +03:00
transfiletriggerin)
transfiletriggerin_patterns = " $arg " ;
declare $section = " $1 " ; shift; ;
transfiletriggerin2)
transfiletriggerin2_patterns = " $arg " ;
declare $section = " $1 " ; shift; ;
transfiletriggerun)
transfiletriggerun_patterns = " $arg " ;
declare $section = " $1 " ; shift; ;
2017-06-29 17:06:36 +03:00
*)
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
2017-07-04 20:04:07 +03:00
echo -e " #!/bin/sh\necho $name - $version - $release . $arch " > $name
2017-06-29 17:06:36 +03:00
chmod a+x $name
$build
${ pretrans : +%pretrans }
$pretrans
${ pre : +%pre }
$pre
2017-07-13 03:50:08 +03:00
${ post : +%post } ${ post_args }
2017-06-29 17:06:36 +03:00
$post
${ posttrans : +%posttrans }
$posttrans
2017-07-07 17:45:10 +03:00
${ transfiletriggerin : +%transfiletriggerin -- ${ transfiletriggerin_patterns } }
$transfiletriggerin
${ transfiletriggerin2 : +%transfiletriggerin -- ${ transfiletriggerin2_patterns } }
$transfiletriggerin2
${ transfiletriggerun : +%transfiletriggerun -- ${ transfiletriggerun_patterns } }
$transfiletriggerun
2017-06-29 17:06:36 +03:00
%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
}
2017-09-18 22:11:26 +03:00
# build an SELinux package ready to be installed -- really, we just support file
# context entries for now, though it's enough to test policy changes
# $1 - package name
# $2+ - pairs of file path regex and context types
build_selinux_rpm( ) {
local name = $1 ; shift
local module_dir = $test_tmpdir /policies/$name
mkdir -p $module_dir
local module_te = $module_dir /$name .te
local module_fc = $module_dir /$name .fc
# also declare a type associated with the app; any non-trivial SELinux
# package will have some type enforcement rules that will require policy
# recompilation
cat > $module_te <<EOF
policy_module( ${ name } , 1.0.0)
type ${ name } _t;
EOF
echo -n "" > $module_fc
while [ $# -ne 0 ] ; do
local fc_regex = $1 ; shift
local fc_type = $1 ; shift
local fc_label = " gen_context(system_u:object_r: $fc_type ,s0) "
echo " $fc_regex -- $fc_label " >> $module_fc
done
make -C $module_dir -f /usr/share/selinux/devel/Makefile $name .pp
# We point the spec file directly at our pp. This is a bit underhanded, but
# it's cleaner than copying it in and using e.g. Source0 or something.
local pp = $( realpath $module_dir /$name .pp)
local install_dir = /usr/share/selinux/packages
build_rpm $name install " mkdir -p %{buildroot} ${ install_dir }
install ${ pp } %{ buildroot} ${ install_dir } " \
post " semodule -n -i ${ install_dir } / ${ name } .pp " \
files " ${ install_dir } / ${ name } .pp "
}