diff options
Diffstat (limited to 'tests/aux')
-rw-r--r-- | tests/aux/common.sh | 71 | ||||
-rw-r--r-- | tests/aux/tap-functions.sh | 229 |
2 files changed, 300 insertions, 0 deletions
diff --git a/tests/aux/common.sh b/tests/aux/common.sh new file mode 100644 index 0000000..27db133 --- /dev/null +++ b/tests/aux/common.sh @@ -0,0 +1,71 @@ +# Common testsuite functions +# +# Copyright (C) 2019 Patrick McDermott +# +# This file is part of the ProteanOS Development Kit. +# +# The ProteanOS Development Kit is free software: you can redistribute +# it and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# The ProteanOS Development Kit 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with the ProteanOS Development Kit. If not, see +# <http://www.gnu.org/licenses/>. + +LF=' +' + +# is_diff() is based on cmd_is() from opkbuild 4.0.2, with test results passed +# by argument and context added to the diagnostic output. +is_diff() +{ + local description="${1}" + local got="${2}" + local exp="${3}" + shift 3 + local ok= + local diag= + local eof= + + ok=true + diag='' + exec 3<<-EOF + ${got} + EOF + exec 4<<-EOF + ${exp} + EOF + while :; do + eof=0 + read -r got 0<&3 || eof=$((${eof} + 1)) + read -r exp 0<&4 || eof=$((${eof} + 2)) + [ ${eof} -eq 3 ] && break + if [ x"${got}" = x"${exp}" ]; then + diag="${diag} '${got}'${LF}" + else + ok=false + diag="${diag} got: '${got}'${LF}" + diag="${diag} expected: '${exp}'${LF}" + fi + done + exec 3<&- + exec 4<&- + + if ${ok}; then + ok_ -- "${description}" + else + not_ok_ -- "${description}" + diag_ " Failed test '${description}'" + while IFS='' read -r diag; do + diag_ "${diag}" + done <<-EOF + ${diag} + EOF + fi +} diff --git a/tests/aux/tap-functions.sh b/tests/aux/tap-functions.sh new file mode 100644 index 0000000..dd634b3 --- /dev/null +++ b/tests/aux/tap-functions.sh @@ -0,0 +1,229 @@ +# -*- shell-script -*- +# +# Copyright (C) 2011-2018 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +# Helper functions used by TAP-producing tests of the Automake testsuite. + +# +# IMPORTANT: All the functions defined in this file can *not* be used +# from within a subshell, unless explicitly noted otherwise. +# + +# The counts of the TAP test results seen so far: total count and +# per-result counts. +tap_count_=0 +tap_pass_count_=0 +tap_skip_count_=0 +tap_fail_count_=0 +tap_xfail_count_=0 +tap_xpass_count_=0 + +# not COMMAND [ARGS...] +# --------------------- +# Run the given command and invert its exit status. +not () { ! "$@"; } + +# plan_ [unknown|later|lazy|now|NUMBER-OF-PLANNED-TESTS] +# ------------------------------------------------------ +# Print a TAP plan for the given number of tests. This must be called +# before reporting any test result. If called with the special argument +# "unknown" or "later", it will do nothing, expecting the calling script +# to declare the plan later. If called with the special argument "lazy" +# or "now", it will print a TAP plan that accounts for the number of tests +# seen so far. +plan_ () +{ + if test $# -eq 0; then + bailout_ "plan_: missing argument" + elif test $# -ge 2; then + bailout_ "plan_: too many arguments" + elif test x"$planned_" != x"none" && test x"$planned_" != x"later"; then + bailout_ "plan_: called to many times" + elif test x"$1" = x"unknown" || test x"$1" = x"later"; then + # This means we want to get back later to declaring the TAP plan. + planned_=later + return 0 + elif test x"$1" = x"lazy" || test x"$1" = x"now"; then + planned_=$tap_count_ # Number of test results seen so far. + elif test $1 -ge 0; then + planned_=$1 + else + bailout_ "plan_: invalid argument '$1'" + fi + echo "1..$planned_" +} +planned_=none + +# diag_ [EXPLANATION] +# ------------------ +# Report the given text as TAP diagnostic. Assumes the string denoting +# TAP diagnostic lines is stored in the '$diag_string_' variable; this is +# done to allow better interplay with TAP drivers that allow such a string +# to be configured. +diag_ () +{ + test $# -eq 0 || echo "$diag_string_ $*" +} + +# Used by the 'diag_' function above. User-overridable. +diag_string_="#" + +# warn_ [EXPLANATION] +# ------------------ +# Give a warning (using TAP diagnostic). +warn_ () +{ + case $# in + 0) diag_ "WARNING: (unknown warning)";; + *) diag_ "WARNING: $*";; + esac +} + +# result_ RESULT [-D DIRECTIVE] [-r REASON] [--] [DESCRIPTION...] +# --------------------------------------------------------------- +# Report a test case with the given RESULT (valid values are "ok" and +# "not ok") and the given DESCRIPTION (if any). If DIRECTIVE is given +# and non-empty (valid values being "TODO" and "SKIP"), it will be +# reported too, with the REASON (if given) appended. +result_ () +{ + test $# -gt 0 || bailout_ "result_: missing argument" + tap_result_=$1; shift + case $tap_result_ in + "ok"|"not ok") ;; + *) bailout_ "result_: invalid result '$tap_result'" ;; + esac + tap_directive_= tap_reason_= + while test $# -gt 0; do + case $1 in + -D|--directive) tap_directive_=$2; shift;; + -r|--reason) tap_reason_=$2; shift;; + --) shift; break;; + -*) bailout_ "result_: invalid option '$1'";; + *) break;; + esac + shift + done + case $tap_directive_ in + ""|TODO|SKIP) ;; + *) bailout_ "result_: invalid directive '$directive_'" ;; + esac + tap_count_=$(($tap_count_ + 1)) + case $tap_result_,$tap_directive_ in + ok,) # Passed. + tap_pass_count_=$(($tap_pass_count_ + 1)) ;; + not\ ok,TODO) # Expected failure. + tap_xfail_count_=$(($tap_xfail_count_ + 1)) ;; + not\ ok,*) # Failed. + tap_fail_count_=$(($tap_fail_count_ + 1)) ;; + ok,TODO) # Unexpected pass. + tap_xpass_count_=$(($tap_xpass_count_ + 1)) ;; + ok,SKIP) # Skipped. + tap_skip_count_=$(($tap_skip_count_ + 1)) ;; + *) # Can't happen. + bailout_ "internal error in 'result_'" ;; + esac + tap_text_="$tap_result_ $tap_count_" + if test x"$*" != x; then + tap_text_="$tap_text_ - $*" + fi + if test x"$tap_directive_" != x; then + tap_text_="$tap_text_ # $tap_directive_"${tap_reason_:+" $tap_reason_"} + fi + printf '%s\n' "$tap_text_" +} + +# Shorthands for common usages of 'result_'. +ok_ () { result_ 'ok' ${1+"$@"}; } +not_ok_ () { result_ 'not ok' ${1+"$@"}; } +skip_ () { result_ 'ok' -D SKIP ${1+"$@"}; } + +# skip_row_ COUNT [-r REASON] [--] [DESCRIPTION...] +# ------------------------------------------------- +# Report a COUNT of skipped test, with the given reason and descriptions +# (if any). Useful to avoid cascade failures in case a fair number of +# tests depend on an earlier one that failed. +skip_row_ () +{ + skip_count_=$1; shift + for i_ in $(seq_ $skip_count_); do skip_ ${1+"$@"}; done +} + +# skip_all_ [REASON ...] +# ---------------------- +# Skip all the tests in a test script. Must be used before calling 'plan_' +# or reporting any test result. Can't be used from within a subshell. +skip_all_ () +{ + echo "1..0 # SKIP" ${1+"$@"} + planned_=0 + exit 0 +} + +# bailout_ [REASON ...] +# --------------------- +# Stop the execution of the current test suite right now, due to an +# unrecoverable error. Can be called at any point, but cannot be used +# from within a subshell. +bailout_ () +{ + echo 'Bail out!' ${1+"$@"} + exit 99 +} + +# fatal_ [REASON ...] +# ------------------- +# Same as 'bailout_'; for compatibility with 'plain-functions.sh'. +fatal_ () +{ + bailout_ ${1+"$@"} +} + +# framework_failure_ [REASON ...] +# ------------------------------- +# Stop the execution of the current test suite right now, due to an +# unrecoverable error in the set-up of the test case. Can be called +# at any point, but cannot be used from within a subshell. +framework_failure_ () +{ + bailout_ "set-up failure"${1+": $*"} +} + +# command_ok_ TEST-DESCRIPTION [OPTIONS..] [--] CMD [ARGS...] +# ----------------------------------------------------------- +# Helper subroutine for when a TAP result must be determined by the +# outcome of a command. +command_ok_ () +{ + tap_directive_= tap_reason_= + test $# -gt 0 || bailout_ "command_ok_: missing argument" + tap_description_=$1; shift + while test $# -gt 0; do + case $1 in + -D|--directive) tap_directive_=$2; shift;; + -r|--reason) tap_reason_=$2; shift;; + --) shift; break;; + -*) bailout_ "command_ok_: invalid option '$1'";; + *) break;; + esac + shift + done + tap_result_="ok"; "$@" || tap_result_="not ok" + result_ "$tap_result_" -D "$tap_directive_" -r "$tap_reason_" \ + -- "$tap_description_" +} + +: |