SPS · log · files · refs · tags · releases · people · languages · GitHub · file
tests/test_pkconf.sh
5605 bytes at 2909919 · GitHub
#!/bin/sh
set -eu
case $0 in */*) test_dir=${0%/*} ;; *) test_dir=. ;; esac
project_dir=$(CDPATH= cd "$test_dir/.." 2>/dev/null && pwd) || exit 1
fail() { printf 'test_pkconf: %s\n' "$*" >&2; exit 1; }
tmp=$(mktemp -d "${TMPDIR:-/tmp}/sps-pkconf.XXXXXX") || fail 'mktemp failed'
trap 'rm -rf "$tmp"' 0 HUP INT TERM
root=$tmp/root
db=$tmp/db
mkdir -p "$root" "$tmp/cache" "$tmp/build" "$tmp/pkg" "$tmp/recipe"
run()
{
SPS_ROOT=$root SPS_DB=$db SPS_CACHE=$tmp/cache SPS_BUILD=$tmp/build \
SPS_CONFIG=/dev/null SPS_REPOS_CONFIG=/dev/null SPS_PRESERVE=etc \
SPS_LIBDIR=$project_dir/lib "$@"
}
make_pkg()
{
mp_version=$1 mp_text=$2
cat >"$tmp/recipe/recipe" <<EOF_RECIPE
name confpkg
version $mp_version
release 1
arch any
description pkconf fixture
install mkdir -p "\$PKG/etc"
install printf '%s\n' '$mp_text' > "\$PKG/etc/confpkg.conf"
EOF_RECIPE
rm -f "$tmp/pkg/artifact"
run "$project_dir/bin/mkpkg" --artifact-file "$tmp/pkg/artifact" \
--compression none --output "$tmp/pkg" "$tmp/recipe/recipe" >/dev/null 2>&1
sed -n 1p "$tmp/pkg/artifact"
}
# Stage the situation pkconf exists for: a locally edited protected file plus
# an upgrade whose packaged default also changed.
stage()
{
rm -rf "$root" "$db" "$tmp/pkg"
mkdir -p "$root" "$tmp/pkg"
artifact=$(make_pkg 1.0 default-1)
run "$project_dir/bin/pkin" "$artifact" >/dev/null 2>&1
printf '%s\n' local-admin-value >"$root/etc/confpkg.conf"
artifact=$(make_pkg 2.0 default-2)
run "$project_dir/bin/pkin" "$artifact" >/dev/null 2>&1
[ -f "$root/etc/confpkg.conf.sps-new" ] ||
fail 'fixture did not produce a .sps-new sibling'
}
# A clean system has nothing to reconcile.
mkdir -p "$db/installed"
: >"$db/owners"
: >"$db/world"
out=$(run "$project_dir/bin/pkconf" --list) ||
fail 'pkconf --list failed on a clean system'
case $out in
*'No pending packaged configuration defaults.'*) ;;
*) fail "pkconf --list on a clean system said: $out" ;;
esac
# --list reports the pending default.
stage
out=$(run "$project_dir/bin/pkconf" --list) || fail 'pkconf --list failed'
case $out in
*'/etc/confpkg.conf'*) ;;
*) fail "pkconf --list did not report the pending file: $out" ;;
esac
raw=$(run "$project_dir/bin/pkconf" --list --raw) || fail 'pkconf --list --raw failed'
case $raw in
*confpkg*etc/confpkg.conf*modified*) ;;
*) fail "pkconf --list --raw is wrong: $raw" ;;
esac
# --diff compares the live file against the packaged default.
out=$(run "$project_dir/bin/pkconf" --diff /etc/confpkg.conf) ||
fail 'pkconf --diff failed'
case $out in
*local-admin-value*default-2*) ;;
*) fail "pkconf --diff output is wrong: $out" ;;
esac
# The .sps-new spelling must resolve to the same base path.
run "$project_dir/bin/pkconf" --diff /etc/confpkg.conf.sps-new >/dev/null ||
fail 'pkconf --diff did not accept the .sps-new spelling'
# --keep drops the packaged default and leaves the local file alone.
stage
run "$project_dir/bin/pkconf" --keep /etc/confpkg.conf >/dev/null ||
fail 'pkconf --keep failed'
[ "$(cat "$root/etc/confpkg.conf")" = local-admin-value ] ||
fail 'pkconf --keep changed the local file'
[ ! -e "$root/etc/confpkg.conf.sps-new" ] ||
fail 'pkconf --keep left the packaged default behind'
# --accept installs the packaged default. Afterwards the file must match the
# digest pkin recorded, so pkcheck sees a clean package again.
stage
run "$project_dir/bin/pkconf" --accept /etc/confpkg.conf >/dev/null ||
fail 'pkconf --accept failed'
[ "$(cat "$root/etc/confpkg.conf")" = default-2 ] ||
fail 'pkconf --accept did not install the packaged default'
[ ! -e "$root/etc/confpkg.conf.sps-new" ] ||
fail 'pkconf --accept left the packaged default behind'
run "$project_dir/bin/pkcheck" confpkg >/dev/null ||
fail 'pkcheck is unhappy after pkconf --accept'
out=$(run "$project_dir/bin/sget" config-status) || fail 'config-status failed'
case $out in
*'no protected configuration changes'*) ;;
*) fail "config-status is not clean after --accept: $out" ;;
esac
# --backup keeps the replaced local file.
stage
run "$project_dir/bin/pkconf" --accept --backup /etc/confpkg.conf >/dev/null ||
fail 'pkconf --accept --backup failed'
[ "$(cat "$root/etc/confpkg.conf.sps-bak")" = local-admin-value ] ||
fail 'pkconf --backup did not preserve the local file'
# --accept-all and --keep-all operate without naming paths.
stage
run "$project_dir/bin/pkconf" --accept-all >/dev/null ||
fail 'pkconf --accept-all failed'
[ "$(cat "$root/etc/confpkg.conf")" = default-2 ] ||
fail 'pkconf --accept-all did not install the packaged default'
stage
run "$project_dir/bin/pkconf" --keep-all confpkg >/dev/null ||
fail 'pkconf --keep-all failed'
[ "$(cat "$root/etc/confpkg.conf")" = local-admin-value ] ||
fail 'pkconf --keep-all changed the local file'
# A path with no pending default is an error rather than a silent success.
stage
if run "$project_dir/bin/pkconf" --accept /etc/nosuch.conf >/dev/null 2>&1; then
fail 'pkconf --accept accepted a path with no pending default'
fi
# Interactive review refuses to run without a terminal instead of guessing.
stage
if run "$project_dir/bin/pkconf" </dev/null >/dev/null 2>&1; then
fail 'pkconf review should refuse a non-interactive stdin'
fi
# The operations are recorded in the history log.
stage
run "$project_dir/bin/pkconf" --accept /etc/confpkg.conf >/dev/null
grep -q 'config accept /etc/confpkg.conf' "$db/history" ||
fail 'pkconf did not record the accept in history'
printf '%s\n' 'pkconf tests passed'