| git.druid.rocks | index | druid520 | mp | test/ | suites/ | niches.sh |
test/suites/niches.sh
# suite: edge-case niches -- KEYWORDS gating, the mask/hold sugar
# commands' persistence and enforcement, ~ prefix version constraints,
# compound slot tokens (hyphenated slots, -rN revisions), category/name
# cli references, dryrun side-effect-freeness, use-toggle slot
# coexistence, stray stage-dir clean ambiguity, and mp verify's bad-port
# diagnostics.
# accept_keywords gates a pkg_keywords-declaring port (--unmask
# overrides); with ACCEPT_KEYWORDS unset the whole check is off and the
# same port installs freely.
test_keyword_gate() {
t_begin "keyword_gate"
reset_state
printf 'GLOBAL_DEPS=" "\n' >> "$CONF"
mkport ni1kw <<'EOF'
pkg_name="ni1kw"
pkg_ver="1.0"
pkg_keywords="amd64"
install:
touch $MP_PREFIX/ni1kw-installed
remove:
rm -f $MP_PREFIX/ni1kw-installed
EOF
echo 'ACCEPT_KEYWORDS="~arm64"' >> "$CONF"
out=$(mp install ni1kw 2>&1)
rc=$?
assert_exit_nonzero "$rc" "$CUR_TEST" || return
assert_contains "$out" "do not satisfy ACCEPT_KEYWORDS" "$CUR_TEST" || return
assert_file_absent "$MP_PREFIX/ni1kw-installed" "$CUR_TEST" || return
mp install --unmask ni1kw >/tmp/ni1.out 2>&1
assert_file_exists "$MP_PREFIX/ni1kw-installed" "$CUR_TEST" || return
mp remove --force ni1kw >/tmp/ni1.out 2>&1
sed -i '/^ACCEPT_KEYWORDS=/d' "$CONF"
mp install ni1kw >/tmp/ni1.out 2>&1
assert_file_exists "$MP_PREFIX/ni1kw-installed" "$CUR_TEST" || return
t_pass
}
# mp mask persists a MASK=yes entry into the mp-managed pkgconf.conf
# (written value-quoted as MASK="yes" by write_conf) and blocks installs;
# mp unmask lifts it persistently (independent of the one-shot --unmask
# flag).
test_mask_unmask_sugar() {
t_begin "mask_unmask_sugar"
reset_state
printf 'GLOBAL_DEPS=" "\n' >> "$CONF"
mkport ni2m <<'EOF'
pkg_name="ni2m"
pkg_ver="1.0"
install:
touch $MP_PREFIX/ni2m-installed
remove:
rm -f $MP_PREFIX/ni2m-installed
EOF
mp mask ni2m >/tmp/ni2.out 2>&1
pkgconf=$(cat "$WD/pkgconf.conf")
assert_contains "$pkgconf" 'MASK="yes"' "$CUR_TEST" || return
out=$(mp install ni2m 2>&1)
assert_contains "$out" "masked" "$CUR_TEST" || return
assert_file_absent "$MP_PREFIX/ni2m-installed" "$CUR_TEST" || return
mp unmask ni2m >/tmp/ni2.out 2>&1
pkgconf=$(cat "$WD/pkgconf.conf")
assert_not_contains "$pkgconf" 'MASK="yes"' "$CUR_TEST" || return
mp install ni2m >/tmp/ni2.out 2>&1
assert_file_exists "$MP_PREFIX/ni2m-installed" "$CUR_TEST" || return
t_pass
}
# mp hold blocks remove AND reinstall while held; mp unhold restores
# both.
test_hold_lifecycle() {
t_begin "hold_lifecycle"
reset_state
printf 'GLOBAL_DEPS=" "\n' >> "$CONF"
mkport ni3h <<'EOF'
pkg_name="ni3h"
pkg_ver="1.0"
install:
touch $MP_PREFIX/ni3h-installed
remove:
rm -f $MP_PREFIX/ni3h-installed
EOF
mp install ni3h >/tmp/ni3.out 2>&1
mp hold ni3h >/tmp/ni3.out 2>&1
out=$(mp remove ni3h 2>&1)
assert_contains "$out" "held" "$CUR_TEST" || return
assert_file_exists "$MP_PREFIX/ni3h-installed" "$CUR_TEST" || return
out=$(mp reinstall ni3h 2>&1)
assert_contains "$out" "held" "$CUR_TEST" || return
mp unhold ni3h >/tmp/ni3.out 2>&1
mp remove ni3h >/tmp/ni3.out 2>&1
assert_file_absent "$MP_PREFIX/ni3h-installed" "$CUR_TEST" || return
db=$(cat "$WD/db")
assert_not_contains "$db" "ni3h" "$CUR_TEST" || return
t_pass
}
# ~ prefix constraints: "prov~1.2" is satisfied by an installed 1.2.9;
# "prov~9.0" is not, and the consuming install must fail loudly instead
# of silently reusing the mismatched version.
test_tilde_prefix_and_mismatch() {
t_begin "tilde_prefix_and_mismatch"
reset_state
printf 'GLOBAL_DEPS=" "\n' >> "$CONF"
mkport ni4prov <<'EOF'
pkg_name="ni4prov"
pkg_ver="1.2.9"
install:
touch $MP_PREFIX/ni4prov-installed
remove:
rm -f $MP_PREFIX/ni4prov-installed
EOF
mkport ni4ok <<'EOF'
pkg_name="ni4ok"
pkg_ver="1.0"
pkg_deps="ni4prov~1.2"
install:
touch $MP_PREFIX/ni4ok-installed
remove:
rm -f $MP_PREFIX/ni4ok-installed
EOF
mkport ni4bad <<'EOF'
pkg_name="ni4bad"
pkg_ver="1.0"
pkg_deps="ni4prov~9.0"
install:
touch $MP_PREFIX/ni4bad-installed
remove:
rm -f $MP_PREFIX/ni4bad-installed
EOF
mp install ni4prov >/tmp/ni4.out 2>&1
mp install ni4ok >/tmp/ni4.out 2>&1
assert_file_exists "$MP_PREFIX/ni4ok-installed" "$CUR_TEST" || return
out=$(mp install ni4bad 2>&1)
rc=$?
assert_exit_nonzero "$rc" "$CUR_TEST" || return
assert_contains "$out" "does not satisfy" "$CUR_TEST" || return
assert_file_absent "$MP_PREFIX/ni4bad-installed" "$CUR_TEST" || return
t_pass
}
# dep-token grammar niches: a hyphenated compound slot reference
# ("name:12-glibc-znver3-O3") and a version constraint carrying a
# pkgsrc-style -rN revision ("name>=2.0-r1") must both parse and be
# enforced against the installed version.
test_compound_slot_tokens() {
t_begin "compound_slot_tokens"
reset_state
printf 'GLOBAL_DEPS=" "\n' >> "$CONF"
mkport ni5prov <<'EOF'
pkg_name="ni5prov"
pkg_ver="2.0-r1"
pkg_slot="12-glibc-znver3-O3"
install:
touch $MP_PREFIX/ni5prov-installed
remove:
rm -f $MP_PREFIX/ni5prov-installed
EOF
mkport ni5ok <<'EOF'
pkg_name="ni5ok"
pkg_ver="1.0"
pkg_deps="ni5prov:12-glibc-znver3-O3>=2.0-r1"
install:
touch $MP_PREFIX/ni5ok-installed
remove:
rm -f $MP_PREFIX/ni5ok-installed
EOF
mkport ni5bad <<'EOF'
pkg_name="ni5bad"
pkg_ver="1.0"
pkg_deps="ni5prov:12-glibc-znver3-O3>=2.0-r2"
install:
touch $MP_PREFIX/ni5bad-installed
remove:
rm -f $MP_PREFIX/ni5bad-installed
EOF
mp install ni5ok >/tmp/ni5.out 2>&1
rc=$?
assert_exit0 "$rc" "$CUR_TEST" || return
assert_file_exists "$MP_PREFIX/ni5prov-12-glibc-znver3-O3/ni5prov-installed" "$CUR_TEST" || return
db=$(cat "$WD/db")
assert_contains "$db" "ni5prov:12-glibc-znver3-O3 2.0-r1" "$CUR_TEST" || return
out=$(mp install ni5bad 2>&1)
assert_contains "$out" "does not satisfy" "$CUR_TEST" || return
assert_file_absent "$MP_PREFIX/ni5bad-installed" "$CUR_TEST" || return
t_pass
}
# a category/name reference ("scratch/foo") resolves to the port's real
# directory while tracking it in the db under its bare pkg_name.
test_category_slash_install() {
t_begin "category_slash_install"
reset_state
printf 'GLOBAL_DEPS=" "\n' >> "$CONF"
mkport ni6ct <<'EOF'
pkg_name="ni6ct"
pkg_ver="1.0"
install:
touch $MP_PREFIX/ni6ct-installed
remove:
rm -f $MP_PREFIX/ni6ct-installed
EOF
mp install scratch/ni6ct >/tmp/ni6.out 2>&1
rc=$?
assert_exit0 "$rc" "$CUR_TEST" || return
assert_file_exists "$MP_PREFIX/ni6ct-installed" "$CUR_TEST" || return
db=$(cat "$WD/db")
assert_contains "$db" "ni6ct 1.0" "$CUR_TEST" || return
t_pass
}
# mp dryrun must resolve (and print "would install") with zero side
# effects: no staged files, no db entries, nothing on the prefix.
test_dryrun_no_side_effects() {
t_begin "dryrun_no_side_effects"
reset_state
printf 'GLOBAL_DEPS=" "\n' >> "$CONF"
mkport ni7dr <<'EOF'
pkg_name="ni7dr"
pkg_ver="1.0"
install:
touch $MP_PREFIX/ni7dr-installed
remove:
rm -f $MP_PREFIX/ni7dr-installed
EOF
out=$(mp dryrun ni7dr 2>&1)
assert_contains "$out" "would install: ni7dr" "$CUR_TEST" || return
assert_file_absent "$MP_PREFIX/ni7dr-installed" "$CUR_TEST" || return
[ ! -s "$WD/db" ] || { t_fail "$CUR_TEST (db not empty after dryrun)"; return; }
assert_file_absent "$WD/ni7dr" "$CUR_TEST" || return
t_pass
}
# a tag with no provider anywhere in the tree fails with a clear error,
# not a silent no-op.
test_providers_no_provider() {
t_begin "providers_no_provider"
reset_state
out=$(mp providers ni8zzztag 2>&1)
rc=$?
assert_exit_nonzero "$rc" "$CUR_TEST" || return
assert_contains "$out" "no port provides" "$CUR_TEST" || return
t_pass
}
# mp use toggling a pkg_slot_use flag must move the package between two
# coexisting installed slots: enable -> "ni9u:v", disable -> bare "ni9u",
# both present in the db at once (that coexistence is the whole point of
# pkg_slot_use).
test_use_toggle_slot_coexist() {
t_begin "use_toggle_slot_coexist"
reset_state
printf 'GLOBAL_DEPS=" "\n' >> "$CONF"
mkport ni9u <<'EOF'
pkg_name="ni9u"
pkg_ver="1.0"
pkg_slot_use="v"
pkg_use="v"
install:
touch $MP_PREFIX/ni9u-installed
remove:
rm -f $MP_PREFIX/ni9u-installed
EOF
mp use ni9u +v >/tmp/ni9.out 2>&1
mp install ni9u >/tmp/ni9.out 2>&1
assert_file_exists "$MP_PREFIX/ni9u-v/ni9u-installed" "$CUR_TEST" || return
mp use ni9u -v >/tmp/ni9.out 2>&1
mp install ni9u >/tmp/ni9.out 2>&1
assert_file_exists "$MP_PREFIX/ni9u-installed" "$CUR_TEST" || return
db=$(cat "$WD/db")
assert_contains "$db" "ni9u:v" "$CUR_TEST" || return
assert_contains "$db" "ni9u 1.0" "$CUR_TEST" || return
t_pass
}
# mp clean on a bare name matching two stray (db-less) slotted stage
# dirs must report the ambiguity, not pick one silently.
test_clean_ambiguous() {
t_begin "clean_ambiguous"
reset_state
mkdir -p "$WD/ni10x:a" "$WD/ni10x:b"
out=$(mp clean ni10x 2>&1)
rc=$?
assert_exit_nonzero "$rc" "$CUR_TEST" || return
assert_contains "$out" "ambiguous" "$CUR_TEST" || return
assert_file_exists "$WD/ni10x:a" "$CUR_TEST" || return
assert_file_exists "$WD/ni10x:b" "$CUR_TEST" || return
mp clean ni10x:a >/tmp/ni10.out 2>&1
assert_file_absent "$WD/ni10x:a" "$CUR_TEST" || return
assert_file_exists "$WD/ni10x:b" "$CUR_TEST" || return
t_pass
}
# mp verify diagnoses a port with no install phase (and no legacy
# add.sh) and one with an install but no remove phase, exiting nonzero.
test_verify_bad_ports() {
t_begin "verify_bad_ports"
reset_state
mkport ni11nophase <<'EOF'
pkg_name="ni11nophase"
pkg_ver="1.0"
EOF
mkport ni11noremove <<'EOF'
pkg_name="ni11noremove"
pkg_ver="1.0"
install:
touch $MP_PREFIX/ni11noremove-installed
EOF
out=$(mp verify ni11nophase 2>&1)
rc=$?
assert_exit_nonzero "$rc" "$CUR_TEST" || return
assert_contains "$out" "no install phase" "$CUR_TEST" || return
out=$(mp verify ni11noremove 2>&1)
rc=$?
assert_exit_nonzero "$rc" "$CUR_TEST" || return
assert_contains "$out" "no remove phase" "$CUR_TEST" || return
out=$(mp verify ni11fine 2>&1)
rc=$?
assert_exit_nonzero "$rc" "$CUR_TEST" || return
assert_contains "$out" "no such port" "$CUR_TEST" || return
t_pass
}
# ACCEPT_KEYWORDS matrix: bare and ~ arch accept lists against bare and
# ~ port keyword declarations.
kw_case() {
# $1 name, $2 pkg_keywords, $3 ACCEPT_KEYWORDS (or -), $4 expected ("ok"/"blocked")
t_begin "$1"
reset_state
printf 'GLOBAL_DEPS=" "\n' >> "$CONF"
mkport "${1}p" <<EOF
pkg_name="${1}p"
pkg_ver="1.0"
pkg_keywords="$2"
install:
touch \$MP_PREFIX/${1}p-installed
remove:
rm -f \$MP_PREFIX/${1}p-installed
EOF
[ "$3" != "-" ] && printf 'ACCEPT_KEYWORDS="%s"\n' "$3" >> "$CONF"
out=$(mp install "${1}p" 2>&1)
rc=$?
if [ "$4" = "blocked" ]; then
assert_exit_nonzero "$rc" "$CUR_TEST" || return
assert_contains "$out" "do not satisfy ACCEPT_KEYWORDS" "$CUR_TEST" || return
else
assert_exit0 "$rc" "$CUR_TEST" || return
assert_file_exists "$MP_PREFIX/${1}p-installed" "$CUR_TEST" || return
fi
t_pass
}
run_keyword_matrix() {
kw_case kw_bare_accepts_bare 'amd64' 'amd64' ok
kw_case kw_bare_wrong_arch 'amd64' 'arm64' blocked
kw_case kw_tilde_accepts_bare 'amd64' '~amd64' ok
kw_case kw_bare_rejects_tilde_only '~amd64' 'amd64' blocked
kw_case kw_tilde_accepts_tilde '~amd64' '~amd64' ok
kw_case kw_multi_arch 'amd64 x86' 'x86' ok
kw_case kw_multi_arch_missing 'amd64 x86' 'arm64' blocked
}
run_niches_suite() {
test_keyword_gate
test_mask_unmask_sugar
test_hold_lifecycle
test_tilde_prefix_and_mismatch
test_compound_slot_tokens
test_category_slash_install
test_dryrun_no_side_effects
test_providers_no_provider
test_use_toggle_slot_coexist
test_clean_ambiguous
test_verify_bad_ports
run_keyword_matrix
}