042320208e
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.
110 lines
4.8 KiB
Bash
Executable File
110 lines
4.8 KiB
Bash
Executable File
#!/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"
|