diff --git a/test/bats/20-backend-resolution.bats b/test/bats/20-backend-resolution.bats index 51c08bd..415b212 100644 --- a/test/bats/20-backend-resolution.bats +++ b/test/bats/20-backend-resolution.bats @@ -133,6 +133,10 @@ _resolve() { # ADAPTER EXPLICIT -> prints "|" coreutils_path="$(_acq_coreutils_path)" export HOME="$fake_home" export PATH="$coreutils_path" + # Premise: with PATH narrowed to coreutils, the backend MUST be absent — + # otherwise the self-repair path never exercises and the test is vacuous. + run command -v msb + assert_failure # shellcheck source=acq ACQ_SOURCE_ONLY=1 . "$ACQ" # shellcheck source=acq.backends/msb.sh diff --git a/test/bats/helper.bash b/test/bats/helper.bash index 67f573f..84d717d 100644 --- a/test/bats/helper.bash +++ b/test/bats/helper.bash @@ -51,11 +51,18 @@ acq_teardown_stubs() { # the test AND `rm` in bats-exec-test's own teardown. Union the dirs of every # tool we actually rely on so the narrowed PATH is complete regardless of layout. # De-dupes while preserving first-seen order. bash 3.2 safe. +# +# Only absolute paths are unioned: `command -v` resolves shell builtins (e.g. +# printf) to a bare name with no directory, and `dirname` of a bare name yields +# ".", which would silently put the *current directory* on the narrowed PATH — +# a stray file in the CWD would then become callable and defeat the "backend +# provably absent" premise. Skipping non-/-prefixed results keeps PATH clean. _acq_coreutils_path() { local _tools="env rm cat mkdir mv chmod dirname sh grep sed awk printf" local _t _d _seen="" _out="" for _t in $_tools; do _d=$(command -v "$_t" 2>/dev/null) || continue + case "$_d" in /*) ;; *) continue ;; esac _d=$(dirname "$_d") case ":$_seen:" in *":$_d:"*) continue ;; esac _seen="${_seen:+$_seen:}$_d"