/ shtest
shtest
  1  #!/bin/bash
  2  
  3  function test_begin #test [options] - initialize a test run
  4  {
  5      set +e
  6      SHTEST_TESTSUITE=false
  7      export SHTEST_FAIL_CNT=0
  8      export SHTEST_PASS_CNT=0
  9      export SHTEST_SKIP_CNT=0
 10      export SHTEST_FALLTHROUGH=
 11      export SHTEST_VERBOSE=
 12      export SHTEST_VERBOSE=
 13      date >test.log
 14      while [[ $# -ne 0 ]]; do
 15          case "$1" in
 16          --fallthrough) #test skips all remaining tests after the first failure
 17              export SHTEST_FALLTHROUGH=true
 18              ;;
 19          -v|--verbose) #test makes the test run show whats done in detail
 20              export SHTEST_VERBOSE=true
 21              ;;
 22          --trace) #test turns shell tracing on
 23              export SHTEST_VERBOSE=true
 24              set -x
 25              ;;
 26          -h|--help|help) #test show help
 27      less <<EOF
 28    $0 [OPTIONS..]
 29  
 30  OPTIONS
 31  
 32  $(sed 's/^ *\([-|.*[:alpha:]]*\)[^)]*) *#test \([^-]*\)$/  \1\n     \2\n/p;d' < "./shtest" | sed 's/[|]/ /g')
 33  
 34  AVAILABLE TEST (BASH) FUNCTIONS
 35  
 36  $(sed 's/^function \([_[:alnum:]]*\) *#test \([^-]*\) - \(.*\)/  \1 \2\n     \3\n/p;d' < "./rstore")
 37  EOF
 38              exit 0
 39              ;;
 40          --) #test ends shtest arguments, the remaining arguments are passed to the DuT. 
 41              shift
 42              break
 43              ;;
 44          *)
 45              die 1 "unknown parameter: $1"
 46              ;;
 47          esac
 48          shift
 49      done
 50  
 51  }
 52  
 53  function testreport #test  - print the final test statistics
 54  {
 55      tee -a test.log <<EOF
 56  
 57  Tests run:     $(printf "%3d" $((SHTEST_PASS_CNT+SHTEST_FAIL_CNT)))
 58  Tests skipped: $(printf "%3d" "$SHTEST_SKIP_CNT")
 59  Tests passed:  $(printf "%3d" "$SHTEST_PASS_CNT")
 60  Tests failed:  $(printf "%3d" "$SHTEST_FAIL_CNT")
 61  
 62  EOF
 63      echo -n "Overall result: " | tee -a test.log
 64      if [[ $SHTEST_FAIL_CNT -ne 0 ]]; then
 65          red "FAILED"
 66          echo
 67          return 1
 68      else
 69          green "PASSED"
 70          echo
 71          return 0
 72      fi
 73  }
 74  
 75  function shtest_verbose
 76  {
 77      if [[ "$SHTEST_VERBOSE" ]]; then
 78          tee -a test.log
 79      else
 80          cat >>test.log
 81      fi
 82  }
 83  
 84  function ok #test <command> [args...] - call a command that must succeed
 85  {
 86      [[ "$SHTEST_FALLTHROUGH" && "$SHTEST_FAIL_CNT" -gt 0 ]] && { SHTEST_SKIP_CNT=$((SHTEST_SKIP_CNT+1)) ; return 0 ; }
 87      echo -en "\n$(source_info 1): " | shtest_verbose
 88      local cmd="$*"
 89      echo -n "${cmd:0:65}.."  | tee -a test.log
 90      echo | shtest_verbose
 91      ( "$@" ) &> >(shtest_verbose)
 92      # shellcheck disable=SC2181
 93      [[ "$?" -eq 0 ]] || {
 94          echo -ne "\033[70G"
 95          red "FAIL"
 96          SHTEST_FAIL_CNT=$((SHTEST_FAIL_CNT+1))
 97          return 1
 98      }
 99      SHTEST_PASS_CNT=$((SHTEST_PASS_CNT+1))
100      echo -ne "\033[70G"
101      green "OK"
102  }
103  
104  function expect #test <expected> <command> [args...] - call function that must match some expected value on stdout
105  {
106      [[ "$SHTEST_FALLTHROUGH" && "$SHTEST_FAIL_CNT" -gt 0 ]] && { SHTEST_SKIP_CNT=$((SHTEST_SKIP_CNT+1)) ; return 0 ; }
107      echo -en "\n$(source_info 1): " | shtest_verbose
108      local expected="$1"
109      shift
110      local cmd="\$($*) : $expected"
111      echo -n "${cmd:0:65}.." | tee -a test.log
112      echo | shtest_verbose
113      local result
114      result="$("$@")"
115      # shellcheck disable=SC2034
116      local exitcode=$?
117      if [[ "$result" ]]; then
118          if expr "$result" : "$expected" >/dev/null; then
119              SHTEST_PASS_CNT=$((SHTEST_PASS_CNT+1))
120              echo -ne "\033[70G"
121              green "OK"
122          else
123              echo "result was: $result" | shtest_verbose
124              SHTEST_FAIL_CNT=$((SHTEST_FAIL_CNT+1))
125              echo -ne "\033[70G"
126              red "FAIL"
127              return 1
128          fi
129      else
130          echo "command failed" | shtest_verbose
131          SHTEST_FAIL_CNT=$((SHTEST_FAIL_CNT+1))
132          echo -ne "\033[70G"
133          red "FAIL"
134          return 1
135      fi
136  }
137  
138  function skip #test <command> [args...] - skip a unfinished test
139  {
140      [[ "$SHTEST_FALLTHROUGH" && "$SHTEST_FAIL_CNT" -gt 0 ]] && { SHTEST_SKIP_CNT=$((SHTEST_SKIP_CNT+1)) ; return 0 ; }
141      echo -en "\n$(source_info 1): " | shtest_verbose
142      local cmd="$*"
143      echo -n "${cmd:0:65}.." | tee -a test.log
144      echo | shtest_verbose
145      SHTEST_SKIP_CNT=$((SHTEST_SKIP_CNT+1))
146      echo -ne "\033[70G"
147      echo "SKIP" | tee -a test.log
148  }
149  
150  function call #test <command> [args...] - call and log a command when not falling through
151  {
152      [[ "$SHTEST_FALLTHROUGH" && "$SHTEST_FAIL_CNT" -gt 0 ]] && { SHTEST_SKIP_CNT=$((SHTEST_SKIP_CNT+1)) ; return 0 ; }
153      echo -en "\n$(source_info 1): " | shtest_verbose
154      local cmd="$*"
155      echo -n "${cmd:0:65}" | tee -a test.log
156      echo | shtest_verbose
157      "$@" &> >(shtest_verbose)
158      echo -ne "\033[70G"
159      echo "CALL" | tee -a test.log
160  }
161  
162  function source_info # [N] - returns file:line N (or 0) up the bash call stack
163  {
164      echo "${BASH_SOURCE[$((${1:-0}+1))]}:${BASH_LINENO[$((${1:-0}))]}:${FUNCNAME[$((${1:-0}+1))]:+${FUNCNAME[$((${1:-0}+1))]}:}"
165  }
166  
167  function red
168  {
169      echo -en "\033[1;31m"
170      echo -n "$*" | tee -a test.log
171      echo >>test.log
172      echo -e "\033[0m"
173  }
174  
175  function green
176  {
177      echo -en "\033[1;92m"
178      echo -n "$*" | tee -a test.log
179      echo >>test.log
180      echo -e "\033[0m"
181  }
182  
183  export SHTEST_TESTSUITE=true
184  # shellcheck disable=SC1090
185  source "$@"