| #! /bin/sh |
| # Copyright (C) 2025 Free Software Foundation, Inc. |
| # |
| # This program is free software; you can redistribute it and/or modify |
| # it under the terms of the GNU General Public License as published by |
| # the Free Software Foundation; either version 2, or (at your option) |
| # any later version. |
| # |
| # This program is distributed in the hope that it will be useful, |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| # GNU General Public License for more details. |
| # |
| # You should have received a copy of the GNU General Public License |
| # along with this program. If not, see <https://www.gnu.org/licenses/>. |
| |
| # TAP support: |
| # - The Automake TAP driver has an option that instructs it to prefix the |
| # test script's stderr with a given string. |
| |
| . test-init.sh |
| plan_ later |
| |
| dumpf() ( |
| set +x |
| diag_string_='#' diag_ "####### Contents of $1:" |
| diag_ <$1 |
| diag_string_='#' diag_ "#######" |
| ) |
| |
| cat >Makefile.am <<END || bailout_ "failed to create Makefile.am" |
| TESTS = all.test |
| END |
| dumpf Makefile.am |
| |
| . tap-setup.sh |
| |
| # Tests without --stderr-prefix. Historically, the TAP driver has not added |
| # a final newline to either stdout or stderr if the test program did not write |
| # one itself, so that is not tested here. |
| |
| cat >all.test <<END || bailout_ "failed to create all.test" |
| #!/bin/sh |
| echo 1..2 |
| echo ok 1 |
| echo 'Bail out!' >&2 |
| echo ok 2 |
| END |
| chmod a+x all.test || bailout_ "failed to make all.test executable" |
| |
| # Test without --stderr-prefix, without --merge. |
| command_ok_ "no merge, no prefix: make check passes" -- \ |
| run_make -O AM_TEST_LOG_DRIVER_FLAGS= check |
| dumpf all.log |
| command_ok_ "no merge, no prefix: result counts are correct" -- \ |
| count_test_results total=2 pass=2 fail=0 xpass=0 xfail=0 skip=0 error=0 |
| command_ok_ "no merge, no prefix: stderr in log" -- \ |
| grep -q '^Bail out!$' all.log |
| |
| # Test without --stderr-prefix, with --merge. |
| command_ok_ "--merge: make check fails" -- \ |
| run_make -e FAIL AM_TEST_LOG_DRIVER_FLAGS=--merge check |
| dumpf all.log |
| # Don't bother checking the counts -- they're meaningless due to the merged |
| # stderr "corrupting" the TAP output. It is sufficient to just test that |
| # `make check' returned non-zero. |
| command_ok_ "--merge: stderr in log" -- \ |
| grep -q '^Bail out!$' all.log |
| |
| |
| # Tests with --stderr-prefix. If the final stderr line does not have a |
| # terminating newline, the TAP driver should still print the line with the |
| # prefix; a newline is also added to avoid "corrupting" the final prefixed |
| # stderr line with a subsequent stdout line in the log. |
| |
| cat >all.test <<END || bailout_ "failed to create all.test" |
| #!/bin/sh |
| echo 1..2 |
| echo ok 1 |
| echo 'Bail out!' >&2 |
| echo ok 2 |
| printf %s 'final stderr line without newline terminator' >&2 |
| echo "# This comment is written to stdout after the newline-less stderr line" |
| echo "# to ensure that a stdout line written after the final stderr line does" |
| echo "# not get written to the same line in the log as the final stderr line." |
| END |
| chmod a+x all.test || bailout_ "failed to make all.test executable" |
| |
| # Included in the prefix: |
| # 1. quadrigraph for # (@%:@) |
| # 2. literal # (difficult to include in a Makefile variable, but easy to |
| # pass in a command-line make variable assignment) |
| # 3. a string that expands to @%:@ (quadrigraph for #) after quadrigraph |
| # replacement, accomplished by embedding a quadrigraph for the empty |
| # string inside the quadrigraph for # |
| # The end result should be: ##@%:@ |
| PFXFLAG='--stderr-prefix "@%:@#@%@&t@:@ "' |
| |
| # Test with --stderr-prefix, without --merge. |
| command_ok_ "$PFXFLAG: make check passes" -- \ |
| run_make -O AM_TEST_LOG_DRIVER_FLAGS="$PFXFLAG" check |
| dumpf all.log |
| command_ok_ "$PFXFLAG: result counts are correct" -- \ |
| count_test_results total=2 pass=2 fail=0 xpass=0 xfail=0 skip=0 error=0 |
| command_ok_ "$PFXFLAG: prefixed stderr in log" -- \ |
| grep -q '^##@%:@ Bail out!$' all.log |
| command_ok_ "$PFXFLAG: missing final newline is added" -- \ |
| grep -q '^##@%:@ final stderr line without newline terminator$' all.log |
| |
| # Test with --stderr-prefix, with --merge. |
| command_ok_ "$PFXFLAG --merge: make check passes" -- \ |
| run_make -O AM_TEST_LOG_DRIVER_FLAGS="$PFXFLAG --merge" check |
| dumpf all.log |
| command_ok_ "$PFXFLAG --merge: result counts are correct" -- \ |
| count_test_results total=2 pass=2 fail=0 xpass=0 xfail=0 skip=0 error=0 |
| command_ok_ "$PFXFLAG --merge: prefixed stderr in log" -- \ |
| grep -q '^##@%:@ Bail out!$' all.log |
| # Note: When --stderr-prefix is enabled, the TAP driver intentionally waits to |
| # read a complete line before writing it to the log. This reduces the chances |
| # of mixing stderr and stdout in a single log line. If you look at the log |
| # for this test, the final stderr line appears last despite being written by |
| # the test program before the stderr comment lines. This is because the TAP |
| # driver patiently waited for a newline that never came. |
| command_ok_ "$PFXFLAG --merge: missing final newline is added" -- \ |
| grep -q '^##@%:@ final stderr line without newline terminator$' all.log |
| |
| |
| # Test preserved stdout/stderr ordering. The sleeps between writes are |
| # necessary because stdout and stderr are independent and thus inherently race |
| # with each other. (The kernel can wake up the two downstream reader threads |
| # in the opposite order from the upstream writes. Or, if the TAP driver was |
| # changed to use select or poll, the upstream writer can write to both streams |
| # before the kernel wakes up the one downstream reader.) |
| PFXFLAG='--stderr-prefix "# "' |
| desc="$PFXFLAG --merge stdout/stderr ordering" |
| cat >all.test <<END || bailout_ "failed to create all.test" |
| #!/bin/sh |
| echo '1..1' |
| $sleep |
| echo 'stderr 1' >&2 |
| $sleep |
| echo 'ok 1' |
| $sleep |
| echo 'stderr 2' >&2 |
| END |
| chmod a+x all.test || bailout_ "failed to make all.test executable" |
| |
| check_log_line_order() { |
| { |
| grep -xe "$1" all.log |
| grep -xe "$2" all.log |
| sed -n -e '/^\('"$1"'\)$/,${/^\('"$2"'\)$/p}' all.log | grep -xe "$2" |
| } >&2 # Write to stderr in case $1 or $2 looks like a TAP directive. |
| } |
| |
| command_ok_ "$desc: make check passes" -- \ |
| run_make -O AM_TEST_LOG_DRIVER_FLAGS="$PFXFLAG --merge" check |
| dumpf all.log |
| command_ok_ "$desc: result counts are correct" -- \ |
| count_test_results total=1 pass=1 fail=0 xpass=0 xfail=0 skip=0 error=0 |
| command_ok_ "$desc: '1..1' before 'stderr 1'" -- \ |
| check_log_line_order '1\.\.1' '# stderr 1' |
| command_ok_ "$desc: 'stderr 1' before 'ok 1'" -- \ |
| check_log_line_order '# stderr 1' 'ok 1' |
| command_ok_ "$desc: 'ok 1' before 'stderr 2'" -- \ |
| check_log_line_order 'ok 1' '# stderr 2' |
| |
| |
| plan_ now |
| |
| : |