summaryrefslogtreecommitdiff
path: root/t
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2022-06-07 21:10:57 (GMT)
committerJunio C Hamano <gitster@pobox.com>2022-06-07 21:10:57 (GMT)
commitfc5a070f591c2114a6e55b4fe3395f79e93699bb (patch)
tree8d6a907caca61f52958a3271d544b8e17eaa2742 /t
parent2da81d1efb0166e1cec7a8582b837994dde6225b (diff)
parent3069f2a6f4c38e7e599067d2e4a8e31b4f53e2d3 (diff)
downloadgit-fc5a070f591c2114a6e55b4fe3395f79e93699bb.zip
git-fc5a070f591c2114a6e55b4fe3395f79e93699bb.tar.gz
git-fc5a070f591c2114a6e55b4fe3395f79e93699bb.tar.bz2
Merge branch 'js/ci-github-workflow-markup'
Update the GitHub workflow support to make it quicker to get to the failing test. * js/ci-github-workflow-markup: ci: call `finalize_test_case_output` a little later ci(github): mention where the full logs can be found ci: use `--github-workflow-markup` in the GitHub workflow ci(github): avoid printing test case preamble twice ci(github): skip the logs of the successful test cases ci: optionally mark up output in the GitHub workflow ci/run-build-and-tests: add some structure to the GitHub workflow output ci: make it easier to find failed tests' logs in the GitHub workflow ci/run-build-and-tests: take a more high-level view test(junit): avoid line feeds in XML attributes tests: refactor --write-junit-xml code ci: fix code style
Diffstat (limited to 't')
-rw-r--r--t/test-lib-functions.sh6
-rw-r--r--t/test-lib-github-workflow-markup.sh56
-rw-r--r--t/test-lib-junit.sh132
-rw-r--r--t/test-lib.sh128
4 files changed, 212 insertions, 110 deletions
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 50970d3..6da7273 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -795,7 +795,7 @@ test_verify_prereq () {
}
test_expect_failure () {
- test_start_
+ test_start_ "$@"
test "$#" = 3 && { test_prereq=$1; shift; } || test_prereq=
test "$#" = 2 ||
BUG "not 2 or 3 parameters to test-expect-failure"
@@ -803,6 +803,7 @@ test_expect_failure () {
export test_prereq
if ! test_skip "$@"
then
+ test -n "$test_skip_test_preamble" ||
say >&3 "checking known breakage of $TEST_NUMBER.$test_count '$1': $2"
if test_run_ "$2" expecting_failure
then
@@ -815,7 +816,7 @@ test_expect_failure () {
}
test_expect_success () {
- test_start_
+ test_start_ "$@"
test "$#" = 3 && { test_prereq=$1; shift; } || test_prereq=
test "$#" = 2 ||
BUG "not 2 or 3 parameters to test-expect-success"
@@ -823,6 +824,7 @@ test_expect_success () {
export test_prereq
if ! test_skip "$@"
then
+ test -n "$test_skip_test_preamble" ||
say >&3 "expecting success of $TEST_NUMBER.$test_count '$1': $2"
if test_run_ "$2"
then
diff --git a/t/test-lib-github-workflow-markup.sh b/t/test-lib-github-workflow-markup.sh
new file mode 100644
index 0000000..9c5339c
--- /dev/null
+++ b/t/test-lib-github-workflow-markup.sh
@@ -0,0 +1,56 @@
+# Library of functions to mark up test scripts' output suitable for
+# pretty-printing it in GitHub workflows.
+#
+# Copyright (c) 2022 Johannes Schindelin
+#
+# 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 of the License, 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 http://www.gnu.org/licenses/ .
+#
+# The idea is for `test-lib.sh` to source this file when run in GitHub
+# workflows; these functions will then override (empty) functions
+# that are are called at the appropriate times during the test runs.
+
+test_skip_test_preamble=t
+
+start_test_output () {
+ test -n "$GIT_TEST_TEE_OUTPUT_FILE" ||
+ die "--github-workflow-markup requires --verbose-log"
+ github_markup_output="${GIT_TEST_TEE_OUTPUT_FILE%.out}.markup"
+ >$github_markup_output
+ GIT_TEST_TEE_OFFSET=0
+}
+
+# No need to override start_test_case_output
+
+finalize_test_case_output () {
+ test_case_result=$1
+ shift
+ case "$test_case_result" in
+ failure)
+ echo >>$github_markup_output "::error::failed: $this_test.$test_count $1"
+ ;;
+ fixed)
+ echo >>$github_markup_output "::notice::fixed: $this_test.$test_count $1"
+ ;;
+ ok)
+ # Exit without printing the "ok" tests
+ return
+ ;;
+ esac
+ echo >>$github_markup_output "::group::$test_case_result: $this_test.$test_count $*"
+ test-tool >>$github_markup_output path-utils skip-n-bytes \
+ "$GIT_TEST_TEE_OUTPUT_FILE" $GIT_TEST_TEE_OFFSET
+ echo >>$github_markup_output "::endgroup::"
+}
+
+# No need to override finalize_test_output
diff --git a/t/test-lib-junit.sh b/t/test-lib-junit.sh
new file mode 100644
index 0000000..c959183
--- /dev/null
+++ b/t/test-lib-junit.sh
@@ -0,0 +1,132 @@
+# Library of functions to format test scripts' output in JUnit XML
+# format, to support Git's test suite result to be presented in an
+# easily digestible way on Azure Pipelines.
+#
+# Copyright (c) 2022 Johannes Schindelin
+#
+# 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 of the License, 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 http://www.gnu.org/licenses/ .
+#
+# The idea is for `test-lib.sh` to source this file when the user asks
+# for JUnit XML; these functions will then override (empty) functions
+# that are are called at the appropriate times during the test runs.
+
+start_test_output () {
+ junit_xml_dir="$TEST_OUTPUT_DIRECTORY/out"
+ mkdir -p "$junit_xml_dir"
+ junit_xml_base=${1##*/}
+ junit_xml_path="$junit_xml_dir/TEST-${junit_xml_base%.sh}.xml"
+ junit_attrs="name=\"${junit_xml_base%.sh}\""
+ junit_attrs="$junit_attrs timestamp=\"$(TZ=UTC \
+ date +%Y-%m-%dT%H:%M:%S)\""
+ write_junit_xml --truncate "<testsuites>" " <testsuite $junit_attrs>"
+ junit_suite_start=$(test-tool date getnanos)
+ if test -n "$GIT_TEST_TEE_OUTPUT_FILE"
+ then
+ GIT_TEST_TEE_OFFSET=0
+ fi
+}
+
+start_test_case_output () {
+ junit_start=$(test-tool date getnanos)
+}
+
+finalize_test_case_output () {
+ test_case_result=$1
+ shift
+ case "$test_case_result" in
+ ok)
+ set "$*"
+ ;;
+ failure)
+ junit_insert="<failure message=\"not ok $test_count -"
+ junit_insert="$junit_insert $(xml_attr_encode --no-lf "$1")\">"
+ junit_insert="$junit_insert $(xml_attr_encode \
+ "$(if test -n "$GIT_TEST_TEE_OUTPUT_FILE"
+ then
+ test-tool path-utils skip-n-bytes \
+ "$GIT_TEST_TEE_OUTPUT_FILE" $GIT_TEST_TEE_OFFSET
+ else
+ printf '%s\n' "$@" | sed 1d
+ fi)")"
+ junit_insert="$junit_insert</failure>"
+ if test -n "$GIT_TEST_TEE_OUTPUT_FILE"
+ then
+ junit_insert="$junit_insert<system-err>$(xml_attr_encode \
+ "$(cat "$GIT_TEST_TEE_OUTPUT_FILE")")</system-err>"
+ fi
+ set "$1" " $junit_insert"
+ ;;
+ fixed)
+ set "$* (breakage fixed)"
+ ;;
+ broken)
+ set "$* (known breakage)"
+ ;;
+ skip)
+ message="$(xml_attr_encode --no-lf "$skipped_reason")"
+ set "$1" " <skipped message=\"$message\" />"
+ ;;
+ esac
+
+ junit_attrs="name=\"$(xml_attr_encode --no-lf "$this_test.$test_count $1")\""
+ shift
+ junit_attrs="$junit_attrs classname=\"$this_test\""
+ junit_attrs="$junit_attrs time=\"$(test-tool \
+ date getnanos $junit_start)\""
+ write_junit_xml "$(printf '%s\n' \
+ " <testcase $junit_attrs>" "$@" " </testcase>")"
+ junit_have_testcase=t
+}
+
+finalize_test_output () {
+ if test -n "$junit_xml_path"
+ then
+ test -n "$junit_have_testcase" || {
+ junit_start=$(test-tool date getnanos)
+ write_junit_xml_testcase "all tests skipped"
+ }
+
+ # adjust the overall time
+ junit_time=$(test-tool date getnanos $junit_suite_start)
+ sed -e "s/\(<testsuite.*\) time=\"[^\"]*\"/\1/" \
+ -e "s/<testsuite [^>]*/& time=\"$junit_time\"/" \
+ -e '/^ *<\/testsuite/d' \
+ <"$junit_xml_path" >"$junit_xml_path.new"
+ mv "$junit_xml_path.new" "$junit_xml_path"
+
+ write_junit_xml " </testsuite>" "</testsuites>"
+ write_junit_xml=
+ fi
+}
+
+write_junit_xml () {
+ case "$1" in
+ --truncate)
+ >"$junit_xml_path"
+ junit_have_testcase=
+ shift
+ ;;
+ esac
+ printf '%s\n' "$@" >>"$junit_xml_path"
+}
+
+xml_attr_encode () {
+ if test "x$1" = "x--no-lf"
+ then
+ shift
+ printf '%s' "$*" | test-tool xml-encode
+ else
+ printf '%s\n' "$@" | test-tool xml-encode
+ fi
+}
diff --git a/t/test-lib.sh b/t/test-lib.sh
index 8ba5ca1..736c644 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -137,6 +137,12 @@ mark_option_requires_arg () {
store_arg_to=$2
}
+# These functions can be overridden e.g. to output JUnit XML
+start_test_output () { :; }
+start_test_case_output () { :; }
+finalize_test_case_output () { :; }
+finalize_test_output () { :; }
+
parse_option () {
local opt="$1"
@@ -196,7 +202,10 @@ parse_option () {
tee=t
;;
--write-junit-xml)
- write_junit_xml=t
+ . "$TEST_DIRECTORY/test-lib-junit.sh"
+ ;;
+ --github-workflow-markup)
+ . "$TEST_DIRECTORY/test-lib-github-workflow-markup.sh"
;;
--stress)
stress=t ;;
@@ -664,7 +673,7 @@ exec 6<&0
exec 7>&2
_error_exit () {
- finalize_junit_xml
+ finalize_test_output
GIT_EXIT_OK=t
exit 1
}
@@ -774,35 +783,13 @@ trap '{ code=$?; set +x; } 2>/dev/null; exit $code' INT TERM HUP
# the test_expect_* functions instead.
test_ok_ () {
- if test -n "$write_junit_xml"
- then
- write_junit_xml_testcase "$*"
- fi
test_success=$(($test_success + 1))
say_color "" "ok $test_count - $@"
+ finalize_test_case_output ok "$@"
}
test_failure_ () {
- if test -n "$write_junit_xml"
- then
- junit_insert="<failure message=\"not ok $test_count -"
- junit_insert="$junit_insert $(xml_attr_encode "$1")\">"
- junit_insert="$junit_insert $(xml_attr_encode \
- "$(if test -n "$GIT_TEST_TEE_OUTPUT_FILE"
- then
- test-tool path-utils skip-n-bytes \
- "$GIT_TEST_TEE_OUTPUT_FILE" $GIT_TEST_TEE_OFFSET
- else
- printf '%s\n' "$@" | sed 1d
- fi)")"
- junit_insert="$junit_insert</failure>"
- if test -n "$GIT_TEST_TEE_OUTPUT_FILE"
- then
- junit_insert="$junit_insert<system-err>$(xml_attr_encode \
- "$(cat "$GIT_TEST_TEE_OUTPUT_FILE")")</system-err>"
- fi
- write_junit_xml_testcase "$1" " $junit_insert"
- fi
+ failure_label=$1
test_failure=$(($test_failure + 1))
say_color error "not ok $test_count - $1"
shift
@@ -812,24 +799,19 @@ test_failure_ () {
say_color error "1..$test_count"
_error_exit
fi
+ finalize_test_case_output failure "$failure_label" "$@"
}
test_known_broken_ok_ () {
- if test -n "$write_junit_xml"
- then
- write_junit_xml_testcase "$* (breakage fixed)"
- fi
test_fixed=$(($test_fixed+1))
say_color error "ok $test_count - $@ # TODO known breakage vanished"
+ finalize_test_case_output fixed "$@"
}
test_known_broken_failure_ () {
- if test -n "$write_junit_xml"
- then
- write_junit_xml_testcase "$* (known breakage)"
- fi
test_broken=$(($test_broken+1))
say_color warn "not ok $test_count - $@ # TODO known breakage"
+ finalize_test_case_output broken "$@"
}
test_debug () {
@@ -1104,10 +1086,7 @@ test_start_ () {
test_count=$(($test_count+1))
maybe_setup_verbose
maybe_setup_valgrind
- if test -n "$write_junit_xml"
- then
- junit_start=$(test-tool date getnanos)
- fi
+ start_test_case_output "$@"
}
test_finish_ () {
@@ -1158,15 +1137,10 @@ test_skip () {
case "$to_skip" in
t)
- if test -n "$write_junit_xml"
- then
- message="$(xml_attr_encode "$skipped_reason")"
- write_junit_xml_testcase "$1" \
- " <skipped message=\"$message\" />"
- fi
say_color skip "ok $test_count # skip $1 ($skipped_reason)"
: true
+ finalize_test_case_output skip "$@"
;;
*)
false
@@ -1179,53 +1153,6 @@ test_at_end_hook_ () {
:
}
-write_junit_xml () {
- case "$1" in
- --truncate)
- >"$junit_xml_path"
- junit_have_testcase=
- shift
- ;;
- esac
- printf '%s\n' "$@" >>"$junit_xml_path"
-}
-
-xml_attr_encode () {
- printf '%s\n' "$@" | test-tool xml-encode
-}
-
-write_junit_xml_testcase () {
- junit_attrs="name=\"$(xml_attr_encode "$this_test.$test_count $1")\""
- shift
- junit_attrs="$junit_attrs classname=\"$this_test\""
- junit_attrs="$junit_attrs time=\"$(test-tool \
- date getnanos $junit_start)\""
- write_junit_xml "$(printf '%s\n' \
- " <testcase $junit_attrs>" "$@" " </testcase>")"
- junit_have_testcase=t
-}
-
-finalize_junit_xml () {
- if test -n "$write_junit_xml" && test -n "$junit_xml_path"
- then
- test -n "$junit_have_testcase" || {
- junit_start=$(test-tool date getnanos)
- write_junit_xml_testcase "all tests skipped"
- }
-
- # adjust the overall time
- junit_time=$(test-tool date getnanos $junit_suite_start)
- sed -e "s/\(<testsuite.*\) time=\"[^\"]*\"/\1/" \
- -e "s/<testsuite [^>]*/& time=\"$junit_time\"/" \
- -e '/^ *<\/testsuite/d' \
- <"$junit_xml_path" >"$junit_xml_path.new"
- mv "$junit_xml_path.new" "$junit_xml_path"
-
- write_junit_xml " </testsuite>" "</testsuites>"
- write_junit_xml=
- fi
-}
-
test_atexit_cleanup=:
test_atexit_handler () {
# In a succeeding test script 'test_atexit_handler' is invoked
@@ -1248,7 +1175,7 @@ test_done () {
# removed, so the commands can access pidfiles and socket files.
test_atexit_handler
- finalize_junit_xml
+ finalize_test_output
if test -z "$HARNESS_ACTIVE"
then
@@ -1539,22 +1466,7 @@ fi
# in subprocesses like git equals our $PWD (for pathname comparisons).
cd -P "$TRASH_DIRECTORY" || exit 1
-if test -n "$write_junit_xml"
-then
- junit_xml_dir="$TEST_OUTPUT_DIRECTORY/out"
- mkdir -p "$junit_xml_dir"
- junit_xml_base=${0##*/}
- junit_xml_path="$junit_xml_dir/TEST-${junit_xml_base%.sh}.xml"
- junit_attrs="name=\"${junit_xml_base%.sh}\""
- junit_attrs="$junit_attrs timestamp=\"$(TZ=UTC \
- date +%Y-%m-%dT%H:%M:%S)\""
- write_junit_xml --truncate "<testsuites>" " <testsuite $junit_attrs>"
- junit_suite_start=$(test-tool date getnanos)
- if test -n "$GIT_TEST_TEE_OUTPUT_FILE"
- then
- GIT_TEST_TEE_OFFSET=0
- fi
-fi
+start_test_output "$0"
# Convenience
# A regexp to match 5 and 35 hexdigits