test: seal the fake PATH instead of prepending it
The old harness put .tests/fakebin at the front of $PATH, which fails OPEN: a package manager with no fake fell through to the real one, and an audit of this suite invoked the host's actual `brew`. The twelve one-line fakes are replaced by a single dispatcher every fake symlinks to, plus seal.sh, which builds the WHOLE of $PATH for a run — real binaries for the pure tools, fakes for anything that installs, downloads or needs root, and command-not-found for everything else. Runs go under `env -i` so they inherit nothing. Two audits ship with it: any `have`/`find_tool` probe the seal has never heard of is an error, and the four absolute paths find_tool probes are written to .shadowed so a test needing a tool to be genuinely absent can say so. The dispatcher also fails on demand (FAKE_FAIL), which is what makes the installers' failure paths reachable at all — the apt and npm one-at-a-time retries, note_fail, and cmd_install's non-zero exit had all been unreachable, and all three survived being deleted outright. _curl stands in for every remote the installer talks to and for nothing else: an unrecognised URL is a failed download, so a typo'd host shows up as the failure it would really be. The fzf fake records its argv, which is what makes the picker's bindings testable.
This commit is contained in:
Executable
+109
@@ -0,0 +1,109 @@
|
||||
#!/bin/sh
|
||||
# Build a SEALED bin directory: the whole of $PATH for a run under test.
|
||||
#
|
||||
# sh seal.sh <dir> [--with name ...] [--without name ...]
|
||||
#
|
||||
# The old harness prepended .tests/fakebin to the caller's $PATH. That fails
|
||||
# OPEN: a package manager with no fake here simply fell through to the real one,
|
||||
# and an audit of this suite invoked the host's actual `brew`. The seal fails
|
||||
# CLOSED. It holds exactly two kinds of thing --
|
||||
#
|
||||
# REAL pure, local, side-effect-free tools dotup is entitled to use: awk,
|
||||
# sed, install, sha256sum, tar. Faking these would weaken the test;
|
||||
# `sha256sum` in particular has to be the real one or the checksum
|
||||
# comparison is checking a fixture against itself.
|
||||
# FAKE anything that installs, downloads, or needs root. Symlinks to _fake.
|
||||
#
|
||||
# -- and nothing else. A tool that is neither is command-not-found, which is a
|
||||
# visible failure rather than a silent hand-off to the machine.
|
||||
#
|
||||
# One hole cannot be closed from here and is reported rather than hidden:
|
||||
# find_tool probes /usr/local/bin, /usr/local/go/bin, /home/linuxbrew/... and
|
||||
# /opt/homebrew/bin by ABSOLUTE path, so on a developer box those directories
|
||||
# can satisfy a lookup no matter what PATH says. The seal therefore ships a fake
|
||||
# for every name that is shadowed there -- `command -v` is tried first, so the
|
||||
# fake wins -- and writes the shadow list to <dir>/.shadowed so a test that
|
||||
# needs a tool to be genuinely ABSENT can say so instead of quietly passing.
|
||||
set -eu
|
||||
|
||||
# gzip is here because tar shells out to it: without it `tar xz` dies with
|
||||
# "gzip: not found" -- which is the seal working, and is how it was found.
|
||||
REAL='sh awk grep sed sort cut tr head tail id uname mkdir cp mv rm cat
|
||||
dirname basename chmod mktemp find install sha256sum stty tar gzip ln
|
||||
touch true false env expr wc'
|
||||
# Deliberately NOT here by default, each for a reason a test depends on:
|
||||
# sudo absent means SUDO='' and apt-get is invoked directly, which is the
|
||||
# only way FAKE_FAIL=apt-get can reach the installer at all.
|
||||
# fzf absent is what makes ensure_fzf actually fetch one.
|
||||
# bws absent is what makes the private tier actually install it.
|
||||
FAKE='curl apt-get apt-cache brew npm uv snap flatpak xcode-select
|
||||
git dpkg unzip chezmoi'
|
||||
OPTIONAL='sudo fzf bws nvim go node'
|
||||
|
||||
dir=${1:?usage: seal.sh <dir> [--with name ...] [--without name ...]}; shift
|
||||
# Everything the seal KNOWS about, fixed before --without takes anything out: a
|
||||
# hole punched on purpose is still an accounted-for tool, and must not trip the
|
||||
# coverage audit below.
|
||||
KNOWN="$REAL $FAKE $OPTIONAL"
|
||||
mode=
|
||||
for a in "$@"; do
|
||||
case $a in
|
||||
--with) mode=with ;;
|
||||
--without) mode=without ;;
|
||||
*) case $mode in
|
||||
with) FAKE="$FAKE $a"; KNOWN="$KNOWN $a" ;;
|
||||
without) FAKE=$(printf '%s\n' $FAKE | grep -vx "$a" | tr '\n' ' ') ;;
|
||||
*) echo "seal.sh: stray argument $a" >&2; exit 2 ;;
|
||||
esac ;;
|
||||
esac
|
||||
done
|
||||
|
||||
here=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
|
||||
FB=$here/fakebin
|
||||
[ -x "$FB/_fake" ] || { echo "seal.sh: no $FB/_fake" >&2; exit 1; }
|
||||
|
||||
rm -rf "$dir"; mkdir -p "$dir"
|
||||
ln -s "$FB/_fake" "$dir/_fake"
|
||||
ln -s "$FB/_curl" "$dir/_curl"
|
||||
|
||||
# Resolved by looking, not by `command -v`: an interactive shell reports
|
||||
# aliases and functions, and a symlink to a bare name is a loop.
|
||||
miss=
|
||||
for t in $REAL; do
|
||||
found=
|
||||
for bd in /usr/bin /bin /usr/local/bin /sbin /usr/sbin; do
|
||||
[ -x "$bd/$t" ] && { ln -sf "$bd/$t" "$dir/$t"; found=1; break; }
|
||||
done
|
||||
[ -n "$found" ] || miss="$miss $t"
|
||||
done
|
||||
[ -z "$miss" ] || { echo "seal.sh: host is missing real tools:$miss" >&2; exit 1; }
|
||||
|
||||
for t in $FAKE; do ln -sf "$dir/_fake" "$dir/$t"; done
|
||||
|
||||
# ------------------------------------------------------------- the audits ---
|
||||
# 1. Anything dotup probes for must be accounted for. A new `have foo` with no
|
||||
# fake would otherwise fall through to the host the moment someone adds one.
|
||||
D=${DOTUP_SEAL_TARGET:-$here/../dot_local/bin/executable_dotup}
|
||||
probes=$(grep -v '^[[:space:]]*#' "$D" \
|
||||
| grep -oE '\b(have|find_tool) [a-z][a-z0-9-]*' \
|
||||
| awk '{print $2}' | sort -u || :)
|
||||
unknown=
|
||||
for p in $probes; do
|
||||
case " $KNOWN " in *" $p "*) ;; *) unknown="$unknown $p" ;; esac
|
||||
done
|
||||
[ -z "$unknown" ] || {
|
||||
echo "seal.sh: dotup probes for tools the seal has never heard of:$unknown" >&2
|
||||
echo " add them to REAL, FAKE or OPTIONAL -- do not let them fall through" >&2
|
||||
exit 1; }
|
||||
|
||||
# 2. The absolute-path hole, reported rather than papered over. $KNOWN, not
|
||||
# $FAKE: a name taken out with --without is exactly the name a test wants to
|
||||
# be absent, so it is the one that most needs checking.
|
||||
: > "$dir/.shadowed"
|
||||
for t in $KNOWN; do
|
||||
for bd in /usr/local/bin /usr/local/go/bin /home/linuxbrew/.linuxbrew/bin /opt/homebrew/bin; do
|
||||
[ -x "$bd/$t" ] || continue
|
||||
[ -e "$dir/$t" ] || printf '%s\t%s\n' "$t" "$bd/$t" >> "$dir/.shadowed"
|
||||
done
|
||||
done
|
||||
printf '%s\n' "$dir"
|
||||
Reference in New Issue
Block a user