From 29c0d8233b32ab3ad1dcd7c3bf1161449a386dea Mon Sep 17 00:00:00 2001 From: Andrew Gregory Date: Tue, 23 Dec 2014 16:09:58 -0500 Subject: [PATCH] use tap.sh for bash tests tap.sh is a reusable TAP library that handles test counting and provides useful diagnostic messages on test failures. Signed-off-by: Andrew Gregory Signed-off-by: Allan McRae --- Makefile.am | 2 +- test/scripts/human_to_size_test.sh | 39 ++----- test/scripts/parseopts_test.sh | 44 ++------ test/tap.sh | 163 +++++++++++++++++++++++++++++ test/util/pacsorttest.sh | 36 ++----- test/util/vercmptest.sh | 55 ++-------- 6 files changed, 193 insertions(+), 146 deletions(-) create mode 100644 test/tap.sh diff --git a/Makefile.am b/Makefile.am index e9b3dfa1..01ea4f13 100644 --- a/Makefile.am +++ b/Makefile.am @@ -13,7 +13,7 @@ DISTCHECK_CONFIGURE_FLAGS = --enable-doc --disable-git-version # Some files automatically included, so they aren't specified below: # AUTHORS, COPYING, NEWS, README -EXTRA_DIST = HACKING +EXTRA_DIST = HACKING test/tap.sh # Sample makepkg prototype files pkgdatadir = ${datadir}/${PACKAGE} diff --git a/test/scripts/human_to_size_test.sh b/test/scripts/human_to_size_test.sh index 2dacfd14..e412e836 100755 --- a/test/scripts/human_to_size_test.sh +++ b/test/scripts/human_to_size_test.sh @@ -1,53 +1,26 @@ #!/bin/bash -declare -i testcount=0 fail=0 pass=0 total=15 +source "$(dirname "$0")"/../tap.sh || exit 1 # source the library function lib=${1:-${PMTEST_SCRIPTLIB_DIR}human_to_size.sh} if [[ -z $lib || ! -f $lib ]]; then - printf "Bail out! human_to_size library (%s) could not be located\n" "${lib}" + tap_bail "human_to_size library (%s) could not be located" "${lib}" exit 1 fi . "$lib" if ! type -t human_to_size &>/dev/null; then - printf "Bail out! human_to_size function not found\n" + tap_bail "human_to_size function not found" exit 1 fi parse_hts() { - local input=$1 expected=$2 result - - (( ++testcount )) - - result=$(human_to_size "$1") - if [[ $result = "$expected" ]]; then - (( ++pass )) - printf "ok %d - %s\n" "$testcount" "$input" - else - (( ++fail )) - printf "not ok %d - %s\n" "$testcount" "$input" - printf '# [TEST %3s]: FAIL\n' "$testcount" - printf '# input: %s\n' "$input" - printf '# output: %s\n' "$result" - printf '# expected: %s\n' "$expected" - fi + local input=$1 expected=$2 + tap_is_str "$(human_to_size "$input")" "$expected" "$input" } -summarize() { - if (( !fail )); then - printf '# All %s tests successful\n\n' "$testcount" - exit 0 - else - printf '# %s of %s tests failed\n\n' "$fail" "$testcount" - exit 1 - fi -} -trap 'summarize' EXIT - -printf '# Beginning human_to_size tests\n' - -echo "1..$total" +tap_plan 15 # parse_hts diff --git a/test/scripts/parseopts_test.sh b/test/scripts/parseopts_test.sh index 97679c4f..03e9d0ac 100755 --- a/test/scripts/parseopts_test.sh +++ b/test/scripts/parseopts_test.sh @@ -1,17 +1,17 @@ #!/bin/bash -declare -i testcount=0 pass=0 fail=0 total=25 +source "$(dirname "$0")"/../tap.sh || exit 1 # source the library function lib=${1:-${PMTEST_SCRIPTLIB_DIR}parseopts.sh} if [[ -z $lib || ! -f $lib ]]; then - printf "Bail out! parseopts library ($lib) could not be located\n" + tap_bail "parseopts library ($lib) could not be located" exit 1 fi . "$lib" if ! type -t parseopts &>/dev/null; then - printf "Bail out! parseopts function not found\n" + tap_bail "parseopts function not found" exit 1 fi @@ -25,43 +25,13 @@ OPT_LONG=('allsource' 'asroot' 'ignorearch' 'check' 'clean:' 'cleanall' 'nodeps' parse() { local result=$1 tokencount=$2; shift 2 - - (( ++testcount )) parseopts "$OPT_SHORT" "${OPT_LONG[@]}" -- "$@" 2>/dev/null - test_result "$result" "$tokencount" "$*" "${OPTRET[@]}" + tap_is_int "${#OPTRET[@]}" "$tokencount" "$* - tokencount" + tap_is_str "$result" "${OPTRET[*]}" "$* - result" unset OPTRET } -test_result() { - local result=$1 tokencount=$2 input=$3; shift 3 - - if [[ $result = "$*" ]] && (( tokencount == $# )); then - (( ++pass )) - printf 'ok %d - %s\n' "$testcount" "$input" - else - printf 'not ok %d - %s\n' "$testcount" "$input" - printf '# [TEST %3s]: FAIL\n' "$testcount" - printf '# input: %s\n' "$input" - printf '# output: %s (%s tokens)\n' "$*" "$#" - printf '# expected: %s (%s tokens)\n' "$result" "$tokencount" - (( ++fail )) - fi -} - -summarize() { - if (( !fail )); then - printf '# All %s tests successful\n\n' "$testcount" - exit 0 - else - printf '# %s of %s tests failed\n\n' "$fail" "$testcount" - exit 1 - fi -} -trap 'summarize' EXIT - -printf '# Beginning parseopts tests\n' - -echo "1..$total" +tap_plan 50 # usage: parse test-params... # a failed parse will match only the end of options marker '--' @@ -141,4 +111,6 @@ parse '--force --' 2 --force # exact match on possible stem (opt has optarg) parse '--clean foo --' 3 --clean=foo +tap_finish + # vim: set noet: diff --git a/test/tap.sh b/test/tap.sh new file mode 100644 index 00000000..38852691 --- /dev/null +++ b/test/tap.sh @@ -0,0 +1,163 @@ +# Copyright 2014 Andrew Gregory +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# +# Project URL: http://github.com/andrewgregory/tap.sh + +declare -i tap_planned=0 tap_run=0 tap_failed=0 tap_passed=0 +declare tap_todo='' + +tap_plan() { + tap_planned=$1 + printf "1..%d\n" "$tap_planned" +} + +tap_done_testing() { + tap_plan $tap_run +} + +tap_skip_all() { + printf "1..0 # SKIP" + _tap_print_reason " " "$@" + printf "\n" +} + +tap_diag() { + if [[ -n $tap_todo ]]; then + tap_note "$@" + else + tap_note "$@" 1>&2 + fi +} + +tap_note() { + printf "# " + printf -- "$@" + printf "\n" +} + +tap_bail() { + printf "Bail out!" + _tap_print_reason " " "$@" + printf "\n" +} + +tap_finish() { + local tap_todo='' + if (( tap_planned != tap_run )); then + tap_note "Looks like you planned %d tests but ran %d." "$tap_planned" "$tap_run" + elif (( tap_planned == tap_run && tap_failed == 0 )); then + tap_note "All %d tests successfully run." "$tap_planned" + else + tap_note "Failed %d of %d tests." "$tap_failed" "$tap_planned" + fi + (( tap_planned == tap_run && tap_failed == 0 )) +} + +tap_skip() { + local -i count="$1"; shift + while (( count-- )); do + (( tap_run++ )) + printf "ok %d # SKIP" "$tap_run" + _tap_print_reason " " "$@" + printf "\n" + done +} + +_tap_print_reason() { + local sep="$1"; shift + if [[ $# -gt 0 ]]; then + printf "%s" "$sep" + printf -- "$@" + fi +} + +tap_ok() { + local ok="$1"; shift + (( tap_run++ )) + if [[ $ok -eq 0 ]]; then + (( tap_passed++ )) + printf "ok %d" "$tap_run" + else + (( tap_failed++ )) + printf "not ok %d" "$tap_run" + fi + _tap_print_reason " - " "$@" + if [[ -n $tap_todo ]]; then + printf " # TODO %s" "$tap_todo" + fi + printf "\n" + if [[ $ok -ne 0 ]]; then + local line func file + local -i i=0 + + read line func file < <(caller $i) + while [[ -n $func && $func == tap_* ]]; do + (( i++ )) + read line func file < <(caller $i) + done + + if [[ -n $file ]]; then + file=${file##*/} + if [[ -n $tap_todo ]]; then + tap_diag " Failed (TODO) test at %s line %d." "${file}" "$line" + else + tap_diag " Failed test at %s line %d." "${file}" "$line" + fi + fi + fi + return $ok +} + +tap_is_str() { + local got="$1" expected="$2"; shift 2 + [[ $got == $expected ]] + local ret=$? + if ! tap_ok $ret "$@"; then + tap_diag " got: '%s'" "$got" + tap_diag " expected: '%s'" "$expected" + fi + return $ret +} + +tap_is_int() { + local got="$1" expected="$2"; shift 2 + [[ $got -eq $expected ]] + local ret=$? + if ! tap_ok $ret "$@"; then + tap_diag " got: '%s'" "$got" + tap_diag " expected: '%s'" "$expected" + fi + return $ret +} + +tap_diff() { + local got="$1" expected="$2"; shift 2 + local output ret + output="$(diff -u --label got --label expected "$got" "$expected" 2>&1)" + ret=$? + if ! tap_ok $ret "$@"; then + while IFS= read line; do + tap_diag "$line" + done <<<"$output" + fi + return $ret +} + +# vim: ft=sh diff --git a/test/util/pacsorttest.sh b/test/util/pacsorttest.sh index a29d8f19..3414e767 100755 --- a/test/util/pacsorttest.sh +++ b/test/util/pacsorttest.sh @@ -18,15 +18,13 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +source "$(dirname "$0")"/../tap.sh || exit 1 + # default binary if one was not specified as $1 bin=${1:-${PMTEST_UTIL_DIR}pacsort} -# holds counts of tests -total=26 -run=0 -failure=0 if ! type -p "$bin" &>/dev/null; then - echo "Bail out! pacsort binary ($bin) could not be located" + tap_bail "pacsort binary ($bin) could not be located" exit 1 fi @@ -34,24 +32,10 @@ fi # runtest input expected test_description optional_opts runtest() { # run the test - ((run++)) - out=$(diff -u <(printf "$1" | $bin $4) <(printf "$2")) - if [[ $? -eq 0 ]]; then - echo "ok $run - $3" - else - ((failure++)) - echo "not ok $run - $3" - while read line; do - echo " # $line" - done <<<"$out" - fi + tap_diff <(printf "$1" | $bin $4) <(printf "$2") "$3" } -echo "# Running pacsort tests..." - -echo "1..$total" - -# BEGIN TESTS +tap_plan 26 in="1\n2\n3\n4\n" runtest $in $in "already ordered" @@ -124,14 +108,6 @@ runtest "$separator_reverse" "$separator" "really long input, sort key, separato runtest "$separator_reverse" "$separator_reverse" "really long input, sort key, separator, reversed" "-k 3 -t| -r" runtest "$separator" "$separator_reverse" "really long input, sort key, separator, reversed" "-k 3 -t| -r" -#END TESTS - -if [[ $failure -eq 0 ]]; then - echo "# All $run tests successful" - exit 0 -fi - -echo "# $failure of $run tests failed" -exit 1 +tap_finish # vim: set noet: diff --git a/test/util/vercmptest.sh b/test/util/vercmptest.sh index ba279a78..3f626434 100755 --- a/test/util/vercmptest.sh +++ b/test/util/vercmptest.sh @@ -18,57 +18,28 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +source "$(dirname "$0")"/../tap.sh || exit 1 + # default binary if one was not specified as $1 bin=${1:-${PMTEST_UTIL_DIR}vercmp} -# holds counts of tests -total=92 -run=0 -failure=0 # use first arg as our binary if specified if ! type -p "$bin" &>/dev/null; then - echo "Bail out! vercmp binary ($bin) could not be located" + tap_bail "vercmp binary ($bin) could not be located" exit 1 fi -# args: -# pass ver1 ver2 ret expected -pass() { - echo "ok $run - ver1: $1 ver2: $2 ret: $3" -} - -# args: -# fail ver1 ver2 ret expected -fail() { - echo "not ok $run - test: ver1: $1 ver2: $2 ret: $3 expected: $4" - ((failure++)) -} - # args: # runtest ver1 ver2 expected runtest() { - # run the test - ((run++)) - ret=$($bin $1 $2) - func='pass' - [[ -n $ret && $ret -eq $3 ]] || func='fail' - $func $1 $2 $ret $3 + local ver1=$1 ver2=$2 exp=$3 + tap_is_str "$($bin "$ver1" "$ver2")" "$exp" "$ver1 $ver2" # and run its mirror case just to be sure - ((run++)) - reverse=0 - [[ $3 -eq 1 ]] && reverse=-1 - [[ $3 -eq -1 ]] && reverse=1 - ret=$($bin $2 $1) - func='pass' - [[ -n $ret && $ret -eq $reverse ]] || func='fail' - $func $2 $1 $ret $reverse + (( exp *= -1 )) + tap_is_str "$($bin "$ver2" "$ver1")" "$exp" "$ver2 $ver1" } -echo "# Running vercmp tests..." - -echo "1..$total" - -# BEGIN TESTS +tap_plan 92 # all similar length, no pkgrel runtest 1.5.0 1.5.0 0 @@ -142,14 +113,6 @@ runtest 1:1.0 1.0 1 runtest 1:1.0 1.1 1 runtest 1:1.1 1.1 1 -#END TESTS - -if [[ $failure -eq 0 ]]; then - echo "# All $run tests successful" - exit 0 -fi - -echo "# $failure of $run tests failed" -exit 1 +tap_finish # vim: set noet: