#!/bin/bash
# assert.sh 1.1 - bash unit testing framework
# Copyright (C) 2009-2015 Robert Lehmann
#
# http://github.com/lehmannro/assert.sh
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see .
export DISCOVERONLY=${DISCOVERONLY:-}
export DEBUG=${DEBUG:-}
export STOP=${STOP:-}
export INVARIANT=${INVARIANT:-}
export CONTINUE=${CONTINUE:-}
args="$(getopt -n "$0" -l \
verbose,help,stop,discover,invariant,continue vhxdic $*)" \
|| exit -1
for arg in $args; do
case "$arg" in
-h)
echo "$0 [-vxidc]" \
"[--verbose] [--stop] [--invariant] [--discover] [--continue]"
echo "`sed 's/./ /g' <<< "$0"` [-h] [--help]"
exit 0;;
--help)
cat < [stdin]
(( tests_ran++ )) || :
[[ -z "$DISCOVERONLY" ]] || return
expected=$(echo -ne "${2:-}")
result="$(eval 2>/dev/null $1 <<< ${3:-})" || true
if [[ "$result" == "$expected" ]]; then
[[ -z "$DEBUG" ]] || echo -n .
return
fi
result="$(sed -e :a -e '$!N;s/\n/\\n/;ta' <<< "$result")"
[[ -z "$result" ]] && result="nothing" || result="\"$result\""
[[ -z "$2" ]] && expected="nothing" || expected="\"$2\""
_assert_fail "expected $expected${_indent}got $result" "$1" "$3"
}
assert_raises() {
# assert_raises [stdin]
(( tests_ran++ )) || :
[[ -z "$DISCOVERONLY" ]] || return
status=0
(eval $1 <<< ${3:-}) > /dev/null 2>&1 || status=$?
expected=${2:-0}
if [[ "$status" -eq "$expected" ]]; then
[[ -z "$DEBUG" ]] || echo -n .
return
fi
_assert_fail "program terminated with code $status instead of $expected" "$1" "$3"
}
_assert_fail() {
# _assert_fail
[[ -n "$DEBUG" ]] && echo -n X
report="test #$tests_ran \"$2${3:+ <<< $3}\" failed:${_indent}$1"
if [[ -n "$STOP" ]]; then
[[ -n "$DEBUG" ]] && echo
echo "$report"
exit 1
fi
tests_errors[$tests_failed]="$report"
(( tests_failed++ )) || :
}
skip_if() {
# skip_if
(eval $@) > /dev/null 2>&1 && status=0 || status=$?
[[ "$status" -eq 0 ]] || return
skip
}
skip() {
# skip (no arguments)
shopt -q extdebug && tests_extdebug=0 || tests_extdebug=1
shopt -q -o errexit && tests_errexit=0 || tests_errexit=1
# enable extdebug so returning 1 in a DEBUG trap handler skips next command
shopt -s extdebug
# disable errexit (set -e) so we can safely return 1 without causing exit
set +o errexit
tests_trapped=0
trap _skip DEBUG
}
_skip() {
if [[ $tests_trapped -eq 0 ]]; then
# DEBUG trap for command we want to skip. Do not remove the handler
# yet because *after* the command we need to reset extdebug/errexit (in
# another DEBUG trap.)
tests_trapped=1
[[ -z "$DEBUG" ]] || echo -n s
return 1
else
trap - DEBUG
[[ $tests_extdebug -eq 0 ]] || shopt -u extdebug
[[ $tests_errexit -eq 1 ]] || set -o errexit
return 0
fi
}
_assert_reset
: ${tests_suite_status:=0} # remember if any of the tests failed so far
_assert_cleanup() {
local status=$?
# modify exit code if it's not already non-zero
[[ $status -eq 0 && -z $CONTINUE ]] && exit $tests_suite_status
}
trap _assert_cleanup EXIT