summaryrefslogtreecommitdiffstats
path: root/t/test-lib-junit.sh
blob: 79c31c788b921baa3118c918f731ed46b450393b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
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
}