## testlib.bash: shared scaffolding for pave's tests. ## ## Each test file sources this, then builds goal files in a scratch dir ## and runs the real `bin/pave` against them. ## HOME and HOSTNAME point into the scratch dir, so the real machine is never touched. set -euo pipefail PAVE=$(cd -P -- "${BASH_SOURCE[0]%/*}/.." && pwd)/bin/pave scratch=$(mktemp -d) trap 'rm -rf "$scratch"' EXIT export HOME="$scratch/home" export HOSTNAME=testhost unset XDG_STATE_HOME XDG_CONFIG_HOME mkdir -p "$HOME" fails=0 ## pv runs pave, capturing its combined output and exit status. ## ## - @param $1... arguments to pave. ## - @state out the combined stdout and stderr. ## - @state rc the exit status. # shellcheck disable=SC2034 # rc is for the test files to read. pv() { rc=0 out=$("$PAVE" "$@" 2>&1) || rc=$? } ## exact prints a file's content followed by a '.', so a command substitution can't hide trailing newlines. exact() { cat -- "$1" printf . } ## goals writes a goal file, creating its directory. ## ## - @param $1 path of the goal file. ## - @stdin the file's content. goals() { mkdir -p -- "${1%/*}" cat >"$1" } _failed() { >&2 printf 'FAIL: %s\n' "$1" fails=$((fails + 1)) } ## assert checks that a command succeeds. assert() { local label=$1 shift "$@" || _failed "$label" } ## assert_eq checks two strings are equal. assert_eq() { [ "$2" = "$3" ] || _failed "$1 (want '$2', got '$3')" } ## assert_has checks that the last pv output contains a line with the given text. assert_has() { grep -qF -- "$2" <<<"$out" || _failed "$1 (no '$2' in output)" } ## assert_lacks checks that the last pv output doesn't contain the given text. assert_lacks() { ! grep -qF -- "$2" <<<"$out" || _failed "$1 (unwanted '$2' in output)" } ## assert_count checks how many lines of the last pv output contain the given text. assert_count() { local n n=$(grep -cF -- "$2" <<<"$out" || :) assert_eq "$1" "$3" "$n" } ## verdict reports the outcome and exits accordingly. verdict() { local name=${BASH_SOURCE[1]##*/} if [ "$fails" -ne 0 ]; then >&2 echo "$name: $fails case(s) failed." exit 1 fi echo "$name: all cases passed." }