#!/usr/bin/env bash set -e set -E set -T setglobal BATS_COUNT_ONLY = ''"" if test $1 = "-c" { setglobal BATS_COUNT_ONLY = '1' shift } setglobal BATS_EXTENDED_SYNTAX = ''"" if test $1 = "-x" { setglobal BATS_EXTENDED_SYNTAX = $1 shift } setglobal BATS_TEST_FILENAME = $1 if test -z $BATS_TEST_FILENAME { echo "usage: bats-exec " > !2 exit 1 } elif test ! -f $BATS_TEST_FILENAME { echo "bats: $BATS_TEST_FILENAME does not exist" > !2 exit 1 } else { shift } setglobal BATS_TEST_DIRNAME = $[dirname $BATS_TEST_FILENAME] setglobal BATS_TEST_NAMES = ''() proc load { var name = $1 var filename = '' if test $(name:0:1) = "/" { set filename = $(name) } else { set filename = ""$BATS_TEST_DIRNAME/$(name).bash"" } test -f $filename || do { echo "bats: $filename does not exist" > !2 exit 1 } source $(filename) } proc run { var e = '', E = '', T = '', oldIFS = '' [[ ! "$-" =~ e ]] || set e = '1' [[ ! "$-" =~ E ]] || set E = '1' [[ ! "$-" =~ T ]] || set T = '1' set +e set +E set +T setglobal output = $[@Argv !2 > !1] setglobal status = "$Status" set oldIFS = $IFS setglobal IFS = '$'\n',' lines = '('$output) test -z $e || set -e test -z $E || set -E test -z $T || set -T setglobal IFS = $oldIFS } proc setup { true } proc teardown { true } proc skip { setglobal BATS_TEST_SKIPPED = $(1:-1) setglobal BATS_TEST_COMPLETED = '1' exit 0 } proc bats_test_begin { setglobal BATS_TEST_DESCRIPTION = $1 if test -n $BATS_EXTENDED_SYNTAX { echo "begin $BATS_TEST_NUMBER $BATS_TEST_DESCRIPTION" > !3 } setup } proc bats_test_function { var test_name = $1 BATS_TEST_NAMES["$(#BATS_TEST_NAMES[@])"]="$test_name" } proc bats_capture_stack_trace { setglobal BATS_PREVIOUS_STACK_TRACE = '( '"${BATS_CURRENT_STACK_TRACE[@]}" ) setglobal BATS_CURRENT_STACK_TRACE = ''() var test_pattern = "" $BATS_TEST_NAME $BATS_TEST_SOURCE"" var setup_pattern = "" setup $BATS_TEST_SOURCE"" var teardown_pattern = "" teardown $BATS_TEST_SOURCE"" var frame = '' var index = '1' while set frame = $[caller $index] { BATS_CURRENT_STACK_TRACE["$(#BATS_CURRENT_STACK_TRACE[@])"]="$frame" if [[ "$frame" = *"$test_pattern" || \ "$frame" = *"$setup_pattern" || \ "$frame" = *"$teardown_pattern" ]] { break } else { let index+=1 } } setglobal BATS_SOURCE = $[bats_frame_filename $(BATS_CURRENT_STACK_TRACE[0])] setglobal BATS_LINENO = $[bats_frame_lineno $(BATS_CURRENT_STACK_TRACE[0])] } proc bats_print_stack_trace { var frame = '' var index = '1' var count = $(#@) for frame in [@Argv] { var filename = $[bats_trim_filename $[bats_frame_filename $frame]] var lineno = $[bats_frame_lineno $frame] if test $index -eq 1 { echo -n "# (" } else { echo -n "# " } var fn = $[bats_frame_function $frame] if test $fn != $BATS_TEST_NAME { echo -n "from function \`$fn' " } if test $index -eq $count { echo "in test file $filename, line $lineno)" } else { echo "in file $filename, line $lineno," } let index+=1 } } proc bats_print_failed_command { var frame = $1 var status = $2 var filename = $[bats_frame_filename $frame] var lineno = $[bats_frame_lineno $frame] var failed_line = $[bats_extract_line $filename $lineno] var failed_command = $[bats_strip_string $failed_line] echo -n "# \`$(failed_command)' " if test $status -eq 1 { echo "failed" } else { echo "failed with status $status" } } proc bats_frame_lineno { var frame = $1 var lineno = $(frame%% *) echo $lineno } proc bats_frame_function { var frame = $1 var rest = $(frame#* ) var fn = $(rest%% *) echo $fn } proc bats_frame_filename { var frame = $1 var rest = $(frame#* ) var filename = $(rest#* ) if test $filename = $BATS_TEST_SOURCE { echo $BATS_TEST_FILENAME } else { echo $filename } } proc bats_extract_line { var filename = $1 var lineno = $2 sed -n "$(lineno)p" $filename } proc bats_strip_string { var string = $1 printf "%s" $string | sed -e "s/^[ "$'\t'"]*//" -e "s/[ "$'\t'"]*$//" } proc bats_trim_filename { var filename = $1 var length = $(#BATS_CWD) if test $(filename:0:length+1) = "$(BATS_CWD)/" { echo $(filename:length+1) } else { echo $filename } } proc bats_debug_trap { if test $BASH_SOURCE != $1 { bats_capture_stack_trace } } proc bats_error_trap { setglobal BATS_ERROR_STATUS = "$Status" setglobal BATS_ERROR_STACK_TRACE = '( '"${BATS_PREVIOUS_STACK_TRACE[@]}" ) trap - debug } proc bats_teardown_trap { trap "bats_exit_trap" exit var status = '0' teardown >>$BATS_OUT !2 > !1 || set status = "$Status" if test $status -eq 0 { setglobal BATS_TEARDOWN_COMPLETED = '1' } elif test -n $BATS_TEST_COMPLETED { setglobal BATS_ERROR_STATUS = $status setglobal BATS_ERROR_STACK_TRACE = '( '"${BATS_CURRENT_STACK_TRACE[@]}" ) } bats_exit_trap } proc bats_exit_trap { var status = '' var skipped = '' trap - err exit set skipped = ''"" if test -n $BATS_TEST_SKIPPED { set skipped = '" # skip'" if test "1" != $BATS_TEST_SKIPPED { set skipped = "" ($BATS_TEST_SKIPPED)"" } } if test -z $BATS_TEST_COMPLETED || test -z $BATS_TEARDOWN_COMPLETED { echo "not ok $BATS_TEST_NUMBER $BATS_TEST_DESCRIPTION" > !3 bats_print_stack_trace $(BATS_ERROR_STACK_TRACE[@]) > !3 bats_print_failed_command $(BATS_ERROR_STACK_TRACE[${#BATS_ERROR_STACK_TRACE[@]}-1]) $BATS_ERROR_STATUS > !3 sed -e "s/^/# /" < $BATS_OUT > !3 set status = '1' } else { echo "ok $(BATS_TEST_NUMBER)$(skipped) $(BATS_TEST_DESCRIPTION)" > !3 set status = '0' } rm -f $BATS_OUT exit "$status" } proc bats_perform_tests { echo "1..$Argc" setglobal test_number = '1' setglobal status = '0' for test_name in [@Argv] { $0 $BATS_EXTENDED_SYNTAX $BATS_TEST_FILENAME $test_name $test_number || setglobal status = '1' let test_number+=1 } exit "$status" } proc bats_perform_test { setglobal BATS_TEST_NAME = $1 if test $[type -t $BATS_TEST_NAME || true] = "function" { setglobal BATS_TEST_NUMBER = $2 if test -z $BATS_TEST_NUMBER { echo "1..1" setglobal BATS_TEST_NUMBER = '"1'" } setglobal BATS_TEST_COMPLETED = ''"" setglobal BATS_TEARDOWN_COMPLETED = ''"" trap "bats_debug_trap \"\$BASH_SOURCE\"" debug trap "bats_error_trap" err trap "bats_teardown_trap" exit $BATS_TEST_NAME >>$BATS_OUT !2 > !1 setglobal BATS_TEST_COMPLETED = '1' } else { echo "bats: unknown test name \`$BATS_TEST_NAME'" > !2 exit 1 } } if test -z $TMPDIR { setglobal BATS_TMPDIR = '"/tmp'" } else { setglobal BATS_TMPDIR = $(TMPDIR%/) } setglobal BATS_TMPNAME = ""$BATS_TMPDIR/bats.$Pid"" setglobal BATS_PARENT_TMPNAME = ""$BATS_TMPDIR/bats.$PPID"" setglobal BATS_OUT = ""$(BATS_TMPNAME).out"" proc bats_preprocess_source { setglobal BATS_TEST_SOURCE = ""$(BATS_TMPNAME).src"" do { tr -d '\r' < $BATS_TEST_FILENAME; echo; } | bats-preprocess > $BATS_TEST_SOURCE trap "bats_cleanup_preprocessed_source" err exit trap "bats_cleanup_preprocessed_source; exit 1" int } proc bats_cleanup_preprocessed_source { rm -f $BATS_TEST_SOURCE } proc bats_evaluate_preprocessed_source { if test -z $BATS_TEST_SOURCE { setglobal BATS_TEST_SOURCE = ""$(BATS_PARENT_TMPNAME).src"" } source $BATS_TEST_SOURCE } exec !3 3<&1 if test "$Argc" -eq 0 { bats_preprocess_source bats_evaluate_preprocessed_source if test -n $BATS_COUNT_ONLY { echo $(#BATS_TEST_NAMES[@]) } else { bats_perform_tests $(BATS_TEST_NAMES[@]) } } else { bats_evaluate_preprocessed_source bats_perform_test @Argv }