pave

testlib.bash

## 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."
}

tests/testlib.bash · 2.1 KiB · 7240887182