blob: ce00e1dd096b06953b458def98509942656c174d [file] [log] [blame]
#! /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
: