Splux Linux

source-based Linux using SPS

SPS · log · files · refs · tags · releases · people · languages · GitHub · file

tests/test_pkconf.sh


Shell

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'