From 4175ecde16ddbb0637cfafd3a41254d995d8bab7 Mon Sep 17 00:00:00 2001 From: Philipp Gesang Date: Sat, 27 Oct 2018 00:03:50 +0200 Subject: util: sidparse_test. add trivial test wrapper --- _oasis | 6 + util/sidparse_test.sh | 344 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 350 insertions(+) create mode 100755 util/sidparse_test.sh diff --git a/_oasis b/_oasis index c7b8696..c8c8ad0 100644 --- a/_oasis +++ b/_oasis @@ -27,6 +27,12 @@ Test "test_sid" Executable "sidparse" Path: util + CompiledObject: native MainIs: sidparse.ml BuildDepends: sid, stdint, cmdliner, unix +Test "test_sidparse" + Run$: flag(tests) + TestTools: util/sidparse_test.sh + Command: util/sidparse_test.sh + diff --git a/util/sidparse_test.sh b/util/sidparse_test.sh new file mode 100755 index 0000000..feeb9ce --- /dev/null +++ b/util/sidparse_test.sh @@ -0,0 +1,344 @@ +#!/usr/bin/env bash + +set -u + +declare -r SELF=$(basename $0) +declare testme="sidparse.native" +declare verbose=no +declare current_test="" +declare -A tests=() +declare -a failed=() +declare -r default_timeout=5 # s + +declare -r tput_bin=$(command -v tput) + +if [ -t 1 ] && [ -n "${tput_bin:-}" ]; then + declare -rA colors=( \ + [blk]=$("${tput_bin}" setaf 0) \ + [red]=$("${tput_bin}" setaf 1) \ + [grn]=$("${tput_bin}" setaf 2) \ + [ylw]=$("${tput_bin}" setaf 3) \ + [blu]=$("${tput_bin}" setaf 4) \ + [pur]=$("${tput_bin}" setaf 5) \ + [cyn]=$("${tput_bin}" setaf 6) \ + [wht]=$("${tput_bin}" setaf 7) \ + [nil]="" \ + [rst]=$("${tput_bin}" sgr0) \ + ) + + msg () { + local col="${colors[$1]}" + local tag="$2" + local msg="$3" + + printf "[${col}%s${colors[rst]}] %s\n" "${tag}" "${msg}" + } +else + msg () { + local _void="$1" + local tag="$2" + local msg="$3" + + printf "[%s] %s\n" "${tag}" "${msg}" + } +fi + +msg_noise () { + if [ "${verbose:-uhgno}" = yes ]; then + msg pur info "$*" >&2 + fi +} + +msg_error () { + msg red error "$*" >&2 +} + +msg_fatal () { + msg_error $@ + exit -1 +} + +msg_failed () { + local tag="$1" + shift + + msg red "${tag}" "$*" >&2 +} + +msg_good () { + msg grn nice "$*" >&2 +} + +fail () { + local name="$1" + local condition="$2" + local cmd="" + + shift 2 + if [ $# -ne 0 ]; then + cmd=": [$*]" + fi + + local entry="${name} (${condition})${cmd}" + + failed+=( "${entry}" ) +} + +fail_ret () { + local name="$1" + local expect="$2" + local retval="$3" + local reason="$4" + local cmd="" + + shift 4 + if [ $# -ne 0 ]; then + cmd=": [$@]" + fi + + local entry="$(printf "%s (returned=%d, expected=%d, reason=%s)%s" \ + "${name}" ${retval} ${expect} "${reason}" \ + "${cmd}" )" + + failed+=( "${entry}" ) +} + +exit_handler () { + if [ -n "${current_test}" ]; then + msg_error "caught exit while test “${current_test}” was in progress" + fail "${current_test}" exit + fi + + current_test="" +} + +trap exit_handler exit + +assert_equal () { + local name"$1" + local a="$2" + local b="$3" + + if [ "$a" != "$b" ]; then + fail "${name}" "failed comparison; [$a] <> [$b]" + fi +} + +assert_int_equal () { + local name"$1" + local a=$2 + local b=$3 + + if [ $a -ne $b ]; then + fail "${name}" "failed integer comparison; $a <> $b" + fi +} + +register_test () { + local name="$1" + + if [ -n "${tests[${name}]:-}" ]; then + msg_fatal "cannot register test «${name}»: already registered" + fi + + tests["${name}"]="test_${name}" +} + +test_parse_simple () { + local name="$1" + local ret + local cmd=( "./${testme}" S-1-0 ) + + timeout ${default_timeout} ${cmd[@]} &>/dev/null + ret=$? + + case ${ret} in + 0) msg_noise "${name}: success" ;; + 124) fail_ret "${name}" 0 ${ret} "timeout" ${cmd[@]} ;; + 127) fail_ret "${name}" 0 ${ret} "command" ${cmd[@]} ;; + *) fail_ret "${name}" 0 ${ret} "invalid" ${cmd[@]} ;; + esac +} +register_test parse_simple + +test_parse_stdin () { + local name="$1" + local ret + local cmd=( "./${testme}" ) + + timeout ${default_timeout} ${cmd[@]} &>/dev/null <<-STOPTHAT + S-1-0 + S-1-1 + S-1-42-2187-1337 + STOPTHAT + + ret=$? + + case ${ret} in + 0) msg_noise "${name}: success" ;; + 124) fail_ret "${name}" 0 ${ret} "timeout" ${cmd[@]} ;; + 127) fail_ret "${name}" 0 ${ret} "command" ${cmd[@]} ;; + *) fail_ret "${name}" 0 ${ret} "invalid" ${cmd[@]} ;; + esac +} +register_test parse_stdin + +test_parse_garbage_fail () { + local name="$1" + local ret + local cmd=( "./${testme}" ) + + timeout ${default_timeout} ${cmd[@]} "Ook!" &>/dev/null + ret=$? + + case ${ret} in + 255) msg_noise "${name}: success" ;; + 0) fail_ret "${name}" 255 ${ret} "unexpected" ${cmd[@]} ;; + 124) fail_ret "${name}" 255 ${ret} "timeout" ${cmd[@]} ;; + 127) fail_ret "${name}" 255 ${ret} "command" ${cmd[@]} ;; + *) fail_ret "${name}" 255 ${ret} "invalid" ${cmd[@]} ;; + esac +} +register_test parse_garbage_fail + +test_count_output () { + local name="$1" + local ret + local count + local cmd=( "./${testme}" \ + "S-1-42-1337" \ + "S-1-1-2-3-4-5-6-7-8-9" \ + ) + + count=$( timeout ${default_timeout} ${cmd[@]} \ + |wc -l ) + ret=$? + + case ${ret} in + 0) msg_noise "${name}: success" ;; + 124) fail_ret "${name}" 0 ${ret} "timeout" ${cmd[@]} ;; + 127) fail_ret "${name}" 0 ${ret} "command" ${cmd[@]} ;; + *) fail_ret "${name}" 0 ${ret} "invalid" ${cmd[@]} ;; + esac + + assert_int_equal "${name}" ${count} 3 +} +register_test count_output + +test_count_output_quiet () { + # no output at all, even errors + local name="$1" + local count + local cmd=( "./${testme}" --quiet \ + "S-1-42-1337" \ + "Smite you with thunderbolts!" \ + "S-1-1-2-3-4-5-6-7-8-9" \ + ) + + count=$( timeout ${default_timeout} ${cmd[@]} \ + |&wc -c ) + assert_int_equal "${name}" ${count} 0 +} +register_test count_output_quiet + +test_count_output_validate () { + # only error lines + local name="$1" + local count + local wcfd + local cmd=( "./${testme}" --validate \ + "S-1-42-1337" \ + "Smite you with thunderbolts!" \ + "S-1-1-2-3-4-5-6-7-8-9" \ + ) + + count=$( timeout ${default_timeout} "${cmd[@]}" \ + |&wc -l ) + + assert_int_equal "${name}" ${count} 2 +} +register_test count_output_validate + +test_parse_stdin_empty () { + local name="$1" + local ret + local cmd=( "./${testme}" ) + + <<<"" timeout ${default_timeout} "${cmd[@]}" &>/dev/null + ret=$? + + case ${ret} in + 0) msg_noise "${name}: success" ;; + 124) fail_ret "${name}" 0 ${ret} "timeout" ${cmd[@]} ;; + *) fail_ret "${name}" 0 ${ret} "invalid" ${cmd[@]} ;; + esac +} +register_test parse_stdin_empty + +report () { + local n=${#failed[@]} + + if [ $n -eq 0 ]; then + msg_good "all tests completed successfully" + return + fi + + msg_failed report "detected $n failures" + + for f in "${failed[@]}"; do + msg_failed failure "$f" + done +} + +exit_with_status () { + [[ ${#failed[@]} -ne 0 ]] && exit -1 || exit 0 +} + +parse_argv () { + while [ -n "${1:-}" ]; do + case "$1" in + -v|--verbose) + verbose=yes + ;; + -*) + msg_fatal "unknown argument “$1”" + ;; + *) + testme="$1" + ;; + esac + + shift + done +} + +run_test () { + local i=$1 + local name="$2" + + msg_noise "[$i] test «$name»" + current_test="${name}" + "test_${name}" "${name}" + current_test="" +} + +main () { + local i=0 + + parse_argv $@ + + msg_noise "${SELF}: commencing tests for «${testme}»" + + for tst in ${!tests[@]}; do + (( ++i )) + run_test $i "${tst}" + done + + report + + msg_noise "${SELF}: completed $i tests for «${testme}»" + exit_with_status +} + +main $@ + -- cgit v1.2.3