Skip to content

Commit 2ae430b

Browse files
committed
test-lib: pass --tee and --verbose{,-log} through a TAP validator
Change the output under --tee and --verbose so that instead of passing the output through "tee -a" we use our own home-grown "test-tool tee-tap" (the "--verbose" output only goes through it under HARNESS_ACTIVE=true, see below). This ensures the output is valid TAP, allowing our test output to be machine-readable. The --verbose-log mode is the first consumer of that machine-readability, see further discussion below. First, on the history of machine readable TAP output: Both the verbose and non-verbose test outputs were valid TAP back when I added support for TAP in 5099b99 (test-lib: Adjust output to be valid TAP format, 2010-06-24). Sometime after that the --verbose output broke due to some tests emitting their own lines starting "ok" (or otherwise invalidating the TAP). That was noticed and fixed in 452320f (test-lib: add --verbose-log option, 2016-10-21), the problem was that the fix simply turned off the the verbose mode when we were running under TAP::Harness (e.g. under "prove"). That solution worked for running under Travis CI. After that fix it was made to use the --verbose-log option in 041c72d (travis: use --verbose-log test option, 2016-10-21), see 522354d (Add Travis CI support, 2015-11-27) for the "cat t/test-results/*.out" code that was aimed at. But that solution and others discussed in 452320f closed the door on us having reliable machine-readable TAP output. Let's instead revert the work done in 452320f and, as well as the follow-up commits 88c6e9d (test-lib: --valgrind should not override --verbose-log, 2017-09-05) and f5ba2de (test-lib: make "-x" work with "--verbose-log", 2017-12-08), which were only needed to work around bugs in the the previous --verbose-log implementation. Replace it with a simple method for ensuring that we have valid TAP both on stdout, and in any verbose output we write. When we detect that we're running under "prove" we prefix all legitimate TAP directives with "GIT_TEST_TEE_STARTED": $ GIT_TEST_TEE_STARTED=1 ./t5547-push-quarantine.sh GIT_TEST_TEE_STARTED ok 1 - create picky dest repo GIT_TEST_TEE_STARTED ok 2 - accepted objects work [...] GIT_TEST_TEE_STARTED 1..6 Then, instead of piping the output to "tee -a" we pipe it to a helper which first converts "ok" and other TAP syntax to e.g. "\ok", and then strips that "GIT_TEST_TEE_STARTED " prefix from the start of the line, resulting in: $ HARNESS_ACTIVE=t ./t5547-push-quarantine.sh -v 2>&1 | grep -E '^.?ok' ok 1 - create picky dest repo \ok ok 2 - accepted objects work ok 3 - rejected objects are not installed ok 4 - rejected objects are removed ok 5 - push to repo path with path separator (colon) ok 6 - updating a ref from quarantine is forbidden We are thus guaranteed to have valid TAP syntax both on stdout, and in the *.out files in the test-results/* directory. Validating the *.out files isn't needed for now, but will be once we have anything that wants to re-parse that output, e.g. to re-format it on-demand after the tests have been run. These changes would allow us to entirely get rid of the --verbose-log special-case, as noted in 452320f it was only needed to deal with a problem in the TAP output that's now gone away. We might think that it's now redundant to using the -v run to prove itself: prove <test> :: --verbose --tee prove -v <test> :: --verbose --tee However, since its introduction developers have also come to rely on relied on --verbose-log for manually invoking the tests. So we're keeping it. Better yet, since we previous commits set us up to understand TAP verbosity levels. The tests can now be run at differing levels of verbosity, while ensuring that the full output gets logged to test-results/*.out. The -V option (or --verbose-log=1) will emit the same output as it did before. Supplying -V0 (or --verbose-log=0) will strip that output down to have no comments at all, i.e. just TAP directives. Supplying -VV (or --verbose-log=2) will include second-level comments, -VVV (or --verbose-log=3) 3rd-level comments etc. See the comment above "say_color_tap_comment()" introduced in preceding commits for what levels of output are currently emitted. Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
1 parent 2358ff8 commit 2ae430b

File tree

3 files changed

+62
-30
lines changed

3 files changed

+62
-30
lines changed

t/README

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,10 +157,13 @@ appropriately before running "make". Short options can be bundled, i.e.
157157

158158
-V::
159159
--verbose-log::
160-
Write verbose output to the same logfile as `--tee`, but do
161-
_not_ write it to stdout. Unlike `--tee --verbose`, this option
160+
An alias for `--verbose --tee`. This option
162161
is safe to use when stdout is being consumed by a TAP parser
163-
like `prove`. Implies `--tee` and `--verbose`.
162+
like `prove`.
163+
Historically this option was different from `--verbose --tee`
164+
and would not write any verbose output to stdout to ensure the
165+
TAP-correctness of the output. The TAP-correctness of the
166+
output is now sanity checked by the test library,
164167

165168
--with-dashes::
166169
By default tests are run without dashed forms of

t/lib-subtest.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ _run_sub_test_lib_test_common () {
3939
# the sub-test.
4040
sane_unset HARNESS_ACTIVE &&
4141

42+
# Under a top-level --verbose-log we'd get the
43+
# "GIT_TEST_TEE_STARTED " prefix in all our output
44+
# without resetting GIT_TEST_TEE_STARTED (normally it
45+
# guards against recursion).
46+
sane_unset GIT_TEST_TEE_STARTED &&
47+
4248
export TEST_DIRECTORY &&
4349
# The child test re-sources GIT-BUILD-OPTIONS and may thus
4450
# override the test output directory. We thus pass it as an

t/test-lib.sh

Lines changed: 50 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -162,10 +162,31 @@ parse_option () {
162162
--no-chain-lint)
163163
GIT_TEST_CHAIN_LINT=0 ;;
164164
-x)
165-
trace=t ;;
166-
-V|--verbose-log)
167-
verbose_log=t
165+
trace=t
166+
verbose=t
167+
;;
168+
--verbose-log=0)
169+
170+
verbose_log_comment_level=-1
171+
parse_option "--verbose-log"
172+
;;
173+
-V0|-V|--verbose-log)
174+
verbose=t
168175
tee=t
176+
177+
if test "$opt" = "-V0"
178+
then
179+
verbose_log_comment_level=-1
180+
fi
181+
182+
# --verbose-log, unlike --verbose --tee, shows only
183+
# --the TAP on stdout,
184+
verbose_log=--out-only-tap
185+
186+
# TAP comment level via --verbose-log=0, -V, -VV, -VVV etc.
187+
verbose_log_comment_level=${verbose_log_comment_level:-0}
188+
verbose_log_comment_level=$(($verbose_log_comment_level + 1))
189+
169190
;;
170191
--write-junit-xml)
171192
write_junit_xml=t
@@ -220,7 +241,7 @@ do
220241
fi
221242

222243
case "$opt" in
223-
--*|-?)
244+
--*|-?|-V0)
224245
parse_option "$opt" ;;
225246
-?*)
226247
# bundled short options must be fed separately to parse_option
@@ -249,7 +270,7 @@ then
249270
test -z "$verbose" && verbose_only="$valgrind_only"
250271
elif test -n "$valgrind"
251272
then
252-
test -z "$verbose_log" && verbose=t
273+
verbose=t
253274
fi
254275

255276
if test -n "$stress"
@@ -380,7 +401,22 @@ then
380401
(
381402
GIT_TEST_TEE_STARTED=done ${TEST_SHELL_PATH} "$0" "$@" 2>&1
382403
echo $? >"$TEST_RESULTS_BASE.exit"
383-
) | tee -a "$GIT_TEST_TEE_OUTPUT_FILE"
404+
) | "$GIT_BUILD_DIR"/t/helper/test-tool tee-tap \
405+
--prefix="GIT_TEST_TEE_STARTED " \
406+
--file-escape \
407+
${verbose_log:---out-escape} ${verbose_log:+--out-comment-level=$verbose_log_comment_level} \
408+
"$GIT_TEST_TEE_OUTPUT_FILE"
409+
test "$(cat "$TEST_RESULTS_BASE.exit")" = 0
410+
exit
411+
elif test -n "$verbose" && test -n "$HARNESS_ACTIVE"
412+
then
413+
mkdir -p "$TEST_RESULTS_DIR"
414+
(
415+
GIT_TEST_TEE_STARTED=done ${TEST_SHELL_PATH} "$0" "$@" 2>&1
416+
echo $? >"$TEST_RESULTS_BASE.exit"
417+
) | "$GIT_BUILD_DIR"/t/helper/test-tool tee-tap \
418+
--prefix="GIT_TEST_TEE_STARTED " \
419+
--out-escape
384420
test "$(cat "$TEST_RESULTS_BASE.exit")" = 0
385421
exit
386422
fi
@@ -408,10 +444,6 @@ then
408444
trace=
409445
fi
410446
fi
411-
if test -n "$trace" && test -z "$verbose_log"
412-
then
413-
verbose=t
414-
fi
415447

416448
# Since bash 5.0, checkwinsize is enabled by default which does
417449
# update the COLUMNS variable every time a non-builtin command
@@ -626,7 +658,10 @@ else
626658
fi
627659

628660
say_color_tap() {
629-
say_color "$@"
661+
say_color_tap=$1
662+
shift
663+
printf "%s" "${GIT_TEST_TEE_STARTED:+GIT_TEST_TEE_STARTED }"
664+
say_color "$say_color_tap" "$@"
630665
}
631666

632667
# Comments starting with "#" are TAP syntax, we add our own comment
@@ -661,10 +696,11 @@ say_color_tap_comment_lines() {
661696
say_color=$1
662697
shift
663698
say_start=$(say_color_start "$say_color" "")
699+
say_prefix="${GIT_TEST_TEE_STARTED:+GIT_TEST_TEE_STARTED }"
664700
say_reset=$(say_color_reset)
665701

666702
printf '%s\n' "$*" | sed \
667-
-e "s/^/${say_start}${say_level}/" \
703+
-e "s/^/${say_prefix}${say_start}${say_level}/" \
668704
-e "s/$/${say_reset}/"
669705
}
670706

@@ -712,14 +748,6 @@ say () {
712748
say_color info "$*"
713749
}
714750

715-
if test -n "$HARNESS_ACTIVE"
716-
then
717-
if test "$verbose" = t || test -n "$verbose_only"
718-
then
719-
BAIL_OUT 'verbose mode forbidden under TAP harness; try --verbose-log'
720-
fi
721-
fi
722-
723751
test "${test_description}" != "" ||
724752
error "Test script did not set test_description."
725753

@@ -729,10 +757,7 @@ then
729757
exit 0
730758
fi
731759

732-
if test "$verbose_log" = "t"
733-
then
734-
exec 3>>"$GIT_TEST_TEE_OUTPUT_FILE" 4>&3
735-
elif test "$verbose" = "t"
760+
if test "$verbose" = "t"
736761
then
737762
exec 4>&2 3>&1
738763
else
@@ -1023,9 +1048,7 @@ maybe_setup_valgrind () {
10231048

10241049
trace_level_=0
10251050
want_trace () {
1026-
test "$trace" = t && {
1027-
test "$verbose" = t || test "$verbose_log" = t
1028-
}
1051+
test "$trace" = t && test "$verbose" = t
10291052
}
10301053

10311054
# This is a separate function because some tests use

0 commit comments

Comments
 (0)