Commit 213fd7f6 authored by Dom Sekotill's avatar Dom Sekotill
Browse files

Add test framework and tests for has()

parent 3c7ee24d
Loading
Loading
Loading
Loading

.shell/lib/test.bash

0 → 100644
+118 −0
Original line number Diff line number Diff line
set -eu

source ~/.shell/lib/builtins.bash
source ~/.shell/lib/colours.sh

declare -r GOOD_TAG=$(tput setaf $COLOUR_BRIGHT_GREEN)
declare -r BAD_TAG=$(tput setaf $COLOUR_BRIGHT_RED)
declare -r BAD=$(tput setaf $COLOUR_RED)
declare -r INFO_TAG=$(tput setaf $COLOUR_BRIGHT_CYAN)
declare -r INFO=$(tput setaf $COLOUR_CYAN)
declare -r CODE=$(tput setaf $COLOUR_YELLOW)
declare -r COMMENT=$(tput setaf $COLOUR_BLUE)
declare -r RESET=$(tput sgr0)

declare -r PIPES=$(mktemp -td ${XDG_RUNTIME_DIR+-p "$XDG_RUNTIME_DIR"} shlibtest-XXX)
declare -r POUT=$PIPES/stdout PERR=$PIPES/stderr PCODE=$PIPES/code

declare -a SETUP=()
declare -i TESTS=0 FAILURES=0


given() {
	[[ -v SETUP_LINE ]] || SETUP_LINE=${BASH_LINENO[0]}
	SETUP+=( "$*" )
}

when() {
	local setup template fdout fderr fdcode

	TESTS+=1
	TEST_CMD="$*"
	TEST_FILE=${BASH_SOURCE[1]}
	TEST_LINE=${BASH_LINENO[0]}
	TEST_SETUP_LINE=${SETUP_LINE-$TEST_LINE}
	unset SETUP_LINE

	template='
	cmd="%s"
	if ! eval "$cmd"; then
		echo >'$POUT' "$cmd"
		echo >'$PERR' Test setup failed
		echo >'$PCODE' $?
		exit 120
	fi
	'
	printf -v setup "$template" "${SETUP[@]}"
	SETUP=()

	${SHELL-sh} -c "$setup eval '$*' >$POUT 2>$PERR; echo \$? >$PCODE" &
	exec {fdout}<$POUT {fderr}<$PERR
	STDOUT=$(tee <&$fdout)
	STDERR=$(tee <&$fderr)
	exec {fdcode}<$PCODE
	RETVAL=$(tee <&$fdcode)
	wait %1
	exec {fdout}<&- {fderr}<&- {fdcode}<&-
}

expect() {
	eval "$*" && return
	FAILURES+=1
	local line=${BASH_LINENO[0]}
	tee <<-END
		${BAD_TAG}[FAILURE] ${CODE}"$TEST_CMD"
		${BAD}  Test failed at ${INFO}$TEST_FILE: $TEST_LINE

		`show_lines $TEST_SETUP_LINE $line $TEST_FILE`  ${COMMENT}# $*
		${RESET}
	END
	if [[ -n $STDERR ]]; then
		fmt "  ${BAD_TAG}STDERR${RESET}" <<<"$STDERR"
		echo
	fi
} >&2

no_output() { [[ -z "$STDOUT" && -z "$STDERR" ]] && return; }

show_lines() {
	printf "${CODE}"
	sed -n "$1,$2 s/^/  > /p" "${@:3}"
}

fmt() {
	sed "s/^/$1 /" | command fmt ${COLS+-w $COLS} -p "[$1]"
}

completed() {
	trap EXIT
	# kill %+ && wait %+ || true
	rm -r $PIPES
	if [[ -v SIG ]]; then
		echo "${BAD_TAG}[SIGNAL]${RESET} Exit due to signal $SIG"
	elif [[ $EXIT -eq 120 ]]; then
		tee <<-END
			${BAD_TAG}[ERROR] $STDERR during: $TEST_CMD
			${BAD}  Failed command: $STDOUT

			`show_lines $TEST_SETUP_LINE $TEST_LINE $TEST_FILE`
		END
	elif [[ $EXIT -gt 0 ]]; then
		echo "${BAD_TAG}[ERROR]${RESET} Error exit $EXIT"
	elif [[ $TESTS -eq 0 ]]; then
		echo "${INFO_TAG}[NO TESTS]${RESET} No tests where run, was this expected?"
	elif [[ $FAILURES -eq 0 ]]; then
		echo "${GOOD_TAG}[SUCCESS]${RESET} All tests passed"
	else
		echo "${BAD_TAG}[FAIL]${RESET} $FAILURES test(s) failed"
		exit 1
	fi
} >&2


trap 'SIG=INT  completed; exit 130' SIGINT
trap 'SIG=TERM completed; exit 143' SIGTERM
trap 'EXIT=$? completed' EXIT

# Set up pipes
mkfifo $POUT $PERR $PCODE
+18 −0
Original line number Diff line number Diff line
#!/bin/bash
source ~/.shell/lib/test.bash

given  . ~/.shell/lib/shared.sh
when   has this-command-should-definitely-not-exist
expect no_output
expect [[ $RETVAL -eq 1 ]]


given  . ~/.shell/lib/shared.sh
when   has bash
expect no_output
expect [[ $RETVAL -eq 0 ]]

given  . ~/.shell/lib/shared.sh
when   has type
expect no_output
expect [[ $RETVAL -eq 0 ]]