From a894fbfadb147f8426c0850647c82bc3b54706eb Mon Sep 17 00:00:00 2001 From: Martin Schulze Date: Sat, 24 Jul 2021 15:45:44 +0200 Subject: [PATCH 1/4] Add run --keep-empty-lines --- lib/bats-core/test_functions.bash | 45 +++++++++++++++++++++++++------ test/run.bats | 36 +++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 8 deletions(-) create mode 100644 test/run.bats diff --git a/lib/bats-core/test_functions.bash b/lib/bats-core/test_functions.bash index e9fdeb05..ce9417c9 100644 --- a/lib/bats-core/test_functions.bash +++ b/lib/bats-core/test_functions.bash @@ -29,18 +29,47 @@ load() { source "${file}" } -run() { +run() { # [--keep-empty-lines] [--] trap bats_interrupt_trap_in_run INT + local keep_empty_lines= + # parse options starting with - + while [[ $# -gt 0 && $1 == -* ]]; do + case "$1" in + --keep-empty-lines) + keep_empty_lines=1 + ;; + --) + shift # eat the -- before breaking away + break + ;; + esac + shift + done local origFlags="$-" set -f +eET local origIFS="$IFS" - # 'output', 'status', 'lines' are global variables available to tests. - # shellcheck disable=SC2034 - output="$("$@" 2>&1)" - # shellcheck disable=SC2034 - status="$?" - # shellcheck disable=SC2034,SC2206 - IFS=$'\n' lines=($output) + if [[ $keep_empty_lines ]]; then + # 'output', 'status', 'lines' are global variables available to tests. + # preserve trailing newlines by appending . and removing it later + # shellcheck disable=SC2034 + output="$("$@"; status=$?; printf .; exit $status 2>&1)" + output="${output%.}" + lines=() + while IFS= read -r line; do + lines+=("$line") + done <<<"$output" + if [[ -n "$line" ]]; then # if there's any content after the last newline + lines+=("$line") + fi + else + # 'output', 'status', 'lines' are global variables available to tests. + # shellcheck disable=SC2034 + output="$("$@" 2>&1)" + # shellcheck disable=SC2034 + status="$?" + # shellcheck disable=SC2034,SC2206 + IFS=$'\n' lines=($output) + fi IFS="$origIFS" set "-$origFlags" } diff --git a/test/run.bats b/test/run.bats new file mode 100644 index 00000000..86fc031a --- /dev/null +++ b/test/run.bats @@ -0,0 +1,36 @@ +@test "run --keep-empty-lines preserves leading empty lines" { + run --keep-empty-lines echo -n $'\na' + [ "${lines[0]}" == '' ] + [ "${lines[1]}" == a ] + [ ${#lines[@]} -eq 2 ] +} + +@test "run --keep-empty-lines preserves inner empty lines" { + run --keep-empty-lines echo -n $'a\n\nb' + [ "${lines[0]}" == a ] + [ "${lines[1]}" == '' ] + [ "${lines[2]}" == b ] + [ ${#lines[@]} -eq 3 ] +} + +@test "run --keep-empty-lines preserves trailing empty lines" { + run --keep-empty-lines echo -n $'a\n' + [ "${lines[0]}" == a ] + [ "${lines[1]}" == '' ] + [ ${#lines[@]} -eq 2 ] +} + +@test "run --keep-empty-lines preserves multiple trailing empty lines" { + run --keep-empty-lines echo -n $'a\n\n' + [ "${lines[0]}" == a ] + [ "${lines[1]}" == '' ] + [ "${lines[2]}" == '' ] + [ ${#lines[@]} -eq 3 ] +} + +@test "run --keep-empty-lines preserves non-empty trailing line" { + run --keep-empty-lines echo -n $'a\nb' + [ "${lines[0]}" == a ] + [ "${lines[1]}" == b ] + [ ${#lines[@]} -eq 2 ] +} \ No newline at end of file From 6c9b173d1844e599582e12e641ac43877e7b5282 Mon Sep 17 00:00:00 2001 From: Martin Schulze Date: Sat, 24 Jul 2021 22:55:53 +0200 Subject: [PATCH 2/4] run: add --output switch --- lib/bats-core/test_functions.bash | 94 +++++++++++++++++++++++++++---- test/run.bats | 50 ++++++++++++++-- 2 files changed, 127 insertions(+), 17 deletions(-) diff --git a/lib/bats-core/test_functions.bash b/lib/bats-core/test_functions.bash index ce9417c9..db748c00 100644 --- a/lib/bats-core/test_functions.bash +++ b/lib/bats-core/test_functions.bash @@ -29,15 +29,52 @@ load() { source "${file}" } -run() { # [--keep-empty-lines] [--] +bats_suppress_stderr() { + "$@" 2>/dev/null +} + +bats_suppress_stdout() { + "$@" 2>&1 >/dev/null +} + +bats_redirect_stderr_into_file() { + "$@" 2>>"$bats_run_separate_stderr_file" # use >> to see collisions' content +} + +bats_merge_stdout_and_stderr() { + "$@" 2>&1 +} + +# write separate lines from into +bats_separate_lines() { # + output_array_name="$1" + input_var_name="$2" + if [[ $keep_empty_lines ]]; then + local bats_separate_lines_lines=() + while IFS= read -r line; do + bats_separate_lines_lines+=("$line") + done <<<"${!input_var_name}" + eval "${output_array_name}=(\"\${bats_separate_lines_lines[@]}\")" + else + # shellcheck disable=SC2034,SC2206 + IFS=$'\n' read -d '' -r -a $output_array_name <<<"${!input_var_name}" + fi +} + +run() { # [--keep-empty-lines] [--output merged|separate|stderr|stdout] [--] trap bats_interrupt_trap_in_run INT local keep_empty_lines= + local output_case=merged # parse options starting with - while [[ $# -gt 0 && $1 == -* ]]; do case "$1" in --keep-empty-lines) keep_empty_lines=1 ;; + --output) + output_case="$2" + shift 2 # consume the value too! + ;; --) shift # eat the -- before breaking away break @@ -45,6 +82,30 @@ run() { # [--keep-empty-lines] [--] esac shift done + + local pre_command= + + case "$output_case" in + merged) # redirects stderr into stdout and fills only $output/$lines + pre_command=bats_merge_stdout_and_stderr + ;; + separate) # splits stderr into own file and fills $stderr/$stderr_lines too + local bats_run_separate_stderr_file + bats_run_separate_stderr_file="$(mktemp ${BATS_TEST_TMPDIR}/separate-stderr-XXX)" + pre_command=bats_redirect_stderr_into_file + ;; + stderr) # suppresses stdout and fills $stderr/$stderr_lines + pre_command=bats_suppress_stdout + ;; + stdout) # suppresses stderr and fills $output/$lines + pre_command=bats_suppress_stderr + ;; + *) + printf "ERROR: Unknown --output value %s" "$output_case" + return 1 + ;; + esac + local origFlags="$-" set -f +eET local origIFS="$IFS" @@ -52,24 +113,33 @@ run() { # [--keep-empty-lines] [--] # 'output', 'status', 'lines' are global variables available to tests. # preserve trailing newlines by appending . and removing it later # shellcheck disable=SC2034 - output="$("$@"; status=$?; printf .; exit $status 2>&1)" + output="$($pre_command "$@"; status=$?; printf .; exit $status)" + # shellcheck disable=SC2034 + status="$?" output="${output%.}" - lines=() - while IFS= read -r line; do - lines+=("$line") - done <<<"$output" - if [[ -n "$line" ]]; then # if there's any content after the last newline - lines+=("$line") - fi else # 'output', 'status', 'lines' are global variables available to tests. # shellcheck disable=SC2034 - output="$("$@" 2>&1)" + output="$($pre_command "$@")" # shellcheck disable=SC2034 status="$?" - # shellcheck disable=SC2034,SC2206 - IFS=$'\n' lines=($output) fi + + bats_separate_lines lines output + + case "$output_case" in + stderr) + stderr="$output" + stderr_lines=("${lines[@]}") + unset output + unset lines + ;; + separate) + read -d '' -r stderr < "$bats_run_separate_stderr_file" + bats_separate_lines stderr_lines stderr + ;; + esac + IFS="$origIFS" set "-$origFlags" } diff --git a/test/run.bats b/test/run.bats index 86fc031a..b87d88a1 100644 --- a/test/run.bats +++ b/test/run.bats @@ -1,12 +1,14 @@ @test "run --keep-empty-lines preserves leading empty lines" { - run --keep-empty-lines echo -n $'\na' + run --keep-empty-lines -- echo -n $'\na' + printf "'%s'\n" "${lines[@]}" [ "${lines[0]}" == '' ] [ "${lines[1]}" == a ] [ ${#lines[@]} -eq 2 ] } @test "run --keep-empty-lines preserves inner empty lines" { - run --keep-empty-lines echo -n $'a\n\nb' + run --keep-empty-lines -- echo -n $'a\n\nb' + printf "'%s'\n" "${lines[@]}" [ "${lines[0]}" == a ] [ "${lines[1]}" == '' ] [ "${lines[2]}" == b ] @@ -14,14 +16,16 @@ } @test "run --keep-empty-lines preserves trailing empty lines" { - run --keep-empty-lines echo -n $'a\n' + run --keep-empty-lines -- echo -n $'a\n' + printf "'%s'\n" "${lines[@]}" [ "${lines[0]}" == a ] [ "${lines[1]}" == '' ] [ ${#lines[@]} -eq 2 ] } @test "run --keep-empty-lines preserves multiple trailing empty lines" { - run --keep-empty-lines echo -n $'a\n\n' + run --keep-empty-lines -- echo -n $'a\n\n' + printf "'%s'\n" "${lines[@]}" [ "${lines[0]}" == a ] [ "${lines[1]}" == '' ] [ "${lines[2]}" == '' ] @@ -29,8 +33,44 @@ } @test "run --keep-empty-lines preserves non-empty trailing line" { - run --keep-empty-lines echo -n $'a\nb' + run --keep-empty-lines -- echo -n $'a\nb' + printf "'%s'\n" "${lines[@]}" [ "${lines[0]}" == a ] [ "${lines[1]}" == b ] [ ${#lines[@]} -eq 2 ] +} + +print-stderr-stdout() { + printf stdout + printf stderr >&2 +} + +@test "run --output stdout does not print stderr" { + run --output stdout -- print-stderr-stdout + echo "output='$output' stderr='$stderr'" + [ "$output" = "stdout" ] + [ ${#lines[@]} -eq 1 ] + + [ "${stderr-notset}" = notset ] + [ ${#stderr_lines[@]} -eq 0 ] +} + +@test "run --output stderr does not print stdout" { + run --output stderr -- print-stderr-stdout + echo "output='$output' stderr='$stderr'" + [ "${output-notset}" = notset ] + [ ${#lines[@]} -eq 0 ] + + [ "$stderr" = stderr ] + [ ${#stderr_lines[@]} -eq 1 ] +} + +@test "run --output separate splits output" { + run --output separate -- print-stderr-stdout + echo "output='$output' stderr='$stderr'" + [ "$output" = stdout ] + [ ${#lines[@]} -eq 1 ] + + [ "$stderr" = stderr ] + [ ${#stderr_lines[@]} -eq 1 ] } \ No newline at end of file From 205034639d0cd2929f9252404c28c6d98bffff6f Mon Sep 17 00:00:00 2001 From: Martin Schulze Date: Sat, 24 Jul 2021 23:07:04 +0200 Subject: [PATCH 3/4] Fix shellcheck --- lib/bats-core/test_functions.bash | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/bats-core/test_functions.bash b/lib/bats-core/test_functions.bash index db748c00..a5c5e710 100644 --- a/lib/bats-core/test_functions.bash +++ b/lib/bats-core/test_functions.bash @@ -34,6 +34,8 @@ bats_suppress_stderr() { } bats_suppress_stdout() { + # throw away stdout and redirect stderr into stdout + # shellcheck disable=SC2069 "$@" 2>&1 >/dev/null } @@ -57,7 +59,7 @@ bats_separate_lines() { # eval "${output_array_name}=(\"\${bats_separate_lines_lines[@]}\")" else # shellcheck disable=SC2034,SC2206 - IFS=$'\n' read -d '' -r -a $output_array_name <<<"${!input_var_name}" + IFS=$'\n' read -d '' -r -a "$output_array_name" <<<"${!input_var_name}" fi } @@ -91,7 +93,7 @@ run() { # [--keep-empty-lines] [--output merged|separate|stderr|stdout] [--] Date: Sat, 24 Jul 2021 23:11:52 +0200 Subject: [PATCH 4/4] Fix mktemp template --- lib/bats-core/test_functions.bash | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/bats-core/test_functions.bash b/lib/bats-core/test_functions.bash index a5c5e710..1301ff34 100644 --- a/lib/bats-core/test_functions.bash +++ b/lib/bats-core/test_functions.bash @@ -93,7 +93,7 @@ run() { # [--keep-empty-lines] [--output merged|separate|stderr|stdout] [--]