From 3f1cf099deb9c107a42a21095295a96b16f4e765 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Wed, 12 Jun 2019 13:29:36 +0200 Subject: [PATCH 1/5] Check for tests that were not run Can happen e.g. when test code reads stdin which consumes remaining tests and was silently ignored (OK returned) This now makes the test run fail if not all tests were executed --- libexec/bats-core/bats-exec-suite | 16 +++++++++++----- libexec/bats-core/bats-format-tap-stream | 7 +++++++ 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/libexec/bats-core/bats-exec-suite b/libexec/bats-core/bats-exec-suite index eb30d74b..e232b6d2 100755 --- a/libexec/bats-core/bats-exec-suite +++ b/libexec/bats-core/bats-exec-suite @@ -71,16 +71,18 @@ for filename in "$@"; do fi done +test_count="${#all_tests[@]}" + if [[ -n "$count_only_flag" ]]; then - printf '%d\n' "${#all_tests[@]}" + printf '%d\n' "${test_count}" exit fi status=0 -printf '1..%d\n' "${#all_tests[@]}" +printf '1..%d\n' "${test_count}" # No point on continuing if there's no tests. -if [[ "${#all_tests[@]}" == 0 ]]; then +if [[ "${test_count}" == 0 ]]; then exit fi @@ -92,10 +94,14 @@ if [[ "$num_jobs" != 1 ]]; then parallel -qk -j "$num_jobs" --colsep="\t" -- bats-exec-test "${flags[@]}" '{1}' '{2}' '{#}' || status=1 else # Just do it serially. - test_number=1 + test_number=0 while IFS=$'\t' read -r filename test_name; do - bats-exec-test "${flags[@]}" "$filename" "$test_name" "$test_number" || status=1 ((++test_number)) + bats-exec-test "${flags[@]}" "$filename" "$test_name" "$test_number" || status=1 done < <(printf '%s\n' "${all_tests[@]}" | grep -v '^$') + if [[ "${test_number}" != "${test_count}" ]]; then + printf '# bats warning: Only executed %s of %s tests\n' "$test_number" "$test_count" + status=1 + fi fi exit "$status" diff --git a/libexec/bats-core/bats-format-tap-stream b/libexec/bats-core/bats-format-tap-stream index 8c3a9a69..11ce72ba 100755 --- a/libexec/bats-core/bats-format-tap-stream +++ b/libexec/bats-core/bats-format-tap-stream @@ -7,6 +7,7 @@ IFS= read -r header if [[ "$header" =~ $header_pattern ]]; then count="${header:3}" index=0 + passed=0 failures=0 skipped=0 name= @@ -78,6 +79,11 @@ summary() { buffer ', %d skipped' "$skipped" fi + not_run=$((count - passed - failures - skipped)) + if [[ "$not_run" -gt 0 ]]; then + buffer ', %d not run' "$not_run" + fi + buffer '\n' } @@ -158,6 +164,7 @@ while IFS= read -r line; do ((++skipped)) skip "${BASH_REMATCH[2]}" else + ((++passed)) pass fi ;; From 7489346b6fbcf5b004f736b303f9aa5d663bc392 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Wed, 12 Jun 2019 13:47:04 +0200 Subject: [PATCH 2/5] Fix failure if test code reads from stdin Use an array to iterate over to avoid using stdin for test orchestration Fixes #197 --- libexec/bats-core/bats-exec-suite | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/libexec/bats-core/bats-exec-suite b/libexec/bats-core/bats-exec-suite index e232b6d2..9cfca956 100755 --- a/libexec/bats-core/bats-exec-suite +++ b/libexec/bats-core/bats-exec-suite @@ -95,10 +95,15 @@ if [[ "$num_jobs" != 1 ]]; then else # Just do it serially. test_number=0 - while IFS=$'\t' read -r filename test_name; do - ((++test_number)) - bats-exec-test "${flags[@]}" "$filename" "$test_name" "$test_number" || status=1 - done < <(printf '%s\n' "${all_tests[@]}" | grep -v '^$') + for test_line in "${all_tests[@]}"; do + # Only handle non-empty lines + if [[ $test_line ]]; then + filename="${test_line%%$'\t'*}" + test_name="${test_line##*$'\t'}" + ((++test_number)) + bats-exec-test "${flags[@]}" "$filename" "$test_name" "$test_number" || status=1 + fi + done if [[ "${test_number}" != "${test_count}" ]]; then printf '# bats warning: Only executed %s of %s tests\n' "$test_number" "$test_count" status=1 From 88aea00ebfe10455e91cd26d89df0ad83eb1e21f Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Wed, 12 Jun 2019 14:46:35 +0200 Subject: [PATCH 3/5] Add test for a cmd using stdin --- test/fixtures/suite/read_from_stdin/test.bats | 30 +++++++++++++++++++ test/suite.bats | 11 +++++++ 2 files changed, 41 insertions(+) create mode 100644 test/fixtures/suite/read_from_stdin/test.bats diff --git a/test/fixtures/suite/read_from_stdin/test.bats b/test/fixtures/suite/read_from_stdin/test.bats new file mode 100644 index 00000000..7ebcab99 --- /dev/null +++ b/test/fixtures/suite/read_from_stdin/test.bats @@ -0,0 +1,30 @@ +#!/usr/bin/env bats + +function cmd_using_stdin { + # Just reading from stdin + while read -r -t 1 foo; do + if [ "$foo" == "EXIT" ]; then + return 1 + fi + done + echo "OK" + return 0 +} + +@test "test 1" { + run cmd_using_stdin + [ "$status" -eq 0 ] + [ "$output" = "OK" ] +} + +@test "test 2 with TAB in name" { + run cmd_using_stdin + [ "$status" -eq 0 ] + [ "$output" = "OK" ] +} + +@test "test 3" { + run cmd_using_stdin + [ "$status" -eq 0 ] + [ "$output" = "OK" ] +} diff --git a/test/suite.bats b/test/suite.bats index a3fd8f1c..a479c8da 100755 --- a/test/suite.bats +++ b/test/suite.bats @@ -146,3 +146,14 @@ fixtures suite # In theory it should take 3s, but let's give it bit of extra time instead. [[ "$duration" -lt 20 ]] } + +@test "run tests which consume stdin (see #197)" { + run bats "$FIXTURE_ROOT/read_from_stdin" + echo "Status: $status" + echo "Output: $output" + [ "$status" -eq 0 ] + [[ "${lines[0]}" == "1..3" ]] + [[ "${lines[1]}" == "ok 1 test 1" ]] + [[ "${lines[2]}" == "ok 2 test 2 with TAB in name" ]] + [[ "${lines[3]}" == "ok 3 test 3" ]] +} From 3cc78f18a3145a06ab0ffdd60d88cbfbd8a25d0b Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Wed, 3 Jul 2019 09:51:30 +0200 Subject: [PATCH 4/5] Actually read something from stdin Move to bats folder as it is a single test Extracting into an own command file required to use `bash -c` --- test/bats.bats | 9 ++++++ test/fixtures/bats/cmd_using_stdin.bash | 11 +++++++ test/fixtures/bats/read_from_stdin.bats | 20 +++++++++++++ test/fixtures/suite/read_from_stdin/test.bats | 30 ------------------- test/suite.bats | 11 ------- 5 files changed, 40 insertions(+), 41 deletions(-) create mode 100755 test/fixtures/bats/cmd_using_stdin.bash create mode 100644 test/fixtures/bats/read_from_stdin.bats delete mode 100644 test/fixtures/suite/read_from_stdin/test.bats diff --git a/test/bats.bats b/test/bats.bats index 42f32438..1acf8873 100755 --- a/test/bats.bats +++ b/test/bats.bats @@ -483,3 +483,12 @@ END_OF_ERR_MSG # In theory it should take 3s, but let's give it bit of extra time instead. [[ "$duration" -lt 20 ]] } + +@test "run tests which consume stdin (see #197)" { + run bats "$FIXTURE_ROOT/read_from_stdin.bats" + [ "$status" -eq 0 ] + [[ "${lines[0]}" == "1..3" ]] + [[ "${lines[1]}" == "ok 1 test 1" ]] + [[ "${lines[2]}" == "ok 2 test 2 with TAB in name" ]] + [[ "${lines[3]}" == "ok 3 test 3" ]] +} diff --git a/test/fixtures/bats/cmd_using_stdin.bash b/test/fixtures/bats/cmd_using_stdin.bash new file mode 100755 index 00000000..1b1a84b8 --- /dev/null +++ b/test/fixtures/bats/cmd_using_stdin.bash @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + + # Just reading from stdin +while read -r -t 1 foo; do + if [ "$foo" == "EXIT" ]; then + echo "Found" + exit 0 + fi +done +echo "Not found" +exit 1 diff --git a/test/fixtures/bats/read_from_stdin.bats b/test/fixtures/bats/read_from_stdin.bats new file mode 100644 index 00000000..75dca94d --- /dev/null +++ b/test/fixtures/bats/read_from_stdin.bats @@ -0,0 +1,20 @@ +#!/usr/bin/env bats + +@test "test 1" { + # Don't print anything + run bash -c "$BATS_TEST_DIRNAME/cmd_using_stdin.bash" + [ "$status" -eq 1 ] + [ "$output" = "Not found" ] +} + +@test "test 2 with TAB in name" { + run bash -c "echo EXIT | $BATS_TEST_DIRNAME/cmd_using_stdin.bash" + [ "$status" -eq 0 ] + [ "$output" = "Found" ] +} + +@test "test 3" { + run bash -c "echo EXIT | $BATS_TEST_DIRNAME/cmd_using_stdin.bash" + [ "$status" -eq 0 ] + [ "$output" = "Found" ] +} diff --git a/test/fixtures/suite/read_from_stdin/test.bats b/test/fixtures/suite/read_from_stdin/test.bats deleted file mode 100644 index 7ebcab99..00000000 --- a/test/fixtures/suite/read_from_stdin/test.bats +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env bats - -function cmd_using_stdin { - # Just reading from stdin - while read -r -t 1 foo; do - if [ "$foo" == "EXIT" ]; then - return 1 - fi - done - echo "OK" - return 0 -} - -@test "test 1" { - run cmd_using_stdin - [ "$status" -eq 0 ] - [ "$output" = "OK" ] -} - -@test "test 2 with TAB in name" { - run cmd_using_stdin - [ "$status" -eq 0 ] - [ "$output" = "OK" ] -} - -@test "test 3" { - run cmd_using_stdin - [ "$status" -eq 0 ] - [ "$output" = "OK" ] -} diff --git a/test/suite.bats b/test/suite.bats index a479c8da..a3fd8f1c 100755 --- a/test/suite.bats +++ b/test/suite.bats @@ -146,14 +146,3 @@ fixtures suite # In theory it should take 3s, but let's give it bit of extra time instead. [[ "$duration" -lt 20 ]] } - -@test "run tests which consume stdin (see #197)" { - run bats "$FIXTURE_ROOT/read_from_stdin" - echo "Status: $status" - echo "Output: $output" - [ "$status" -eq 0 ] - [[ "${lines[0]}" == "1..3" ]] - [[ "${lines[1]}" == "ok 1 test 1" ]] - [[ "${lines[2]}" == "ok 2 test 2 with TAB in name" ]] - [[ "${lines[3]}" == "ok 3 test 3" ]] -} From bcce61189e9f19651ab60e7bf7143e496c98dc58 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Wed, 3 Jul 2019 15:43:08 +0200 Subject: [PATCH 5/5] Reduce timeout for bash 4+ --- test/fixtures/bats/cmd_using_stdin.bash | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/test/fixtures/bats/cmd_using_stdin.bash b/test/fixtures/bats/cmd_using_stdin.bash index 1b1a84b8..fd94f2d5 100755 --- a/test/fixtures/bats/cmd_using_stdin.bash +++ b/test/fixtures/bats/cmd_using_stdin.bash @@ -1,11 +1,19 @@ #!/usr/bin/env bash - # Just reading from stdin -while read -r -t 1 foo; do +# Fractional timeout supported in bash 4+ +if [ "${BASH_VERSINFO[0]}" -lt 4 ]; then + timeout=1 +else + timeout=0.01 +fi + +# Just reading from stdin +while read -r -t $timeout foo; do if [ "$foo" == "EXIT" ]; then echo "Found" exit 0 fi done + echo "Not found" exit 1