Skip to content

Commit f3baa6d

Browse files
committed
merge main into amd-staging
relands: eea8b44 [GVN] Handle empty attrs in Expression == (llvm#115761) 984bca9 [GVN][NewGVN] Take call attributes into account in expressions (llvm#114545) Reverts: breaks comgr build 41e3919 [clang] Introduce diagnostics suppression mappings (llvm#112517) Change-Id: I3189bf1b5d66b980d2d711c3fe1d5fe217699bb1
2 parents aa2759c + 71d4f34 commit f3baa6d

File tree

288 files changed

+8053
-4002
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

288 files changed

+8053
-4002
lines changed

.ci/generate-buildkite-pipeline-premerge

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ if [[ "${linux_projects}" != "" ]]; then
272272
artifact_paths:
273273
- 'artifacts/**/*'
274274
- '*_result.json'
275-
- 'build/test-results.xml'
275+
- 'build/test-results.*.xml'
276276
agents: ${LINUX_AGENTS}
277277
retry:
278278
automatic:
@@ -295,7 +295,7 @@ if [[ "${windows_projects}" != "" ]]; then
295295
artifact_paths:
296296
- 'artifacts/**/*'
297297
- '*_result.json'
298-
- 'build/test-results.xml'
298+
- 'build/test-results.*.xml'
299299
agents: ${WINDOWS_AGENTS}
300300
retry:
301301
automatic:

.ci/generate_test_report.py

Lines changed: 328 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,328 @@
1+
# Script to parse many JUnit XML result files and send a report to the buildkite
2+
# agent as an annotation.
3+
#
4+
# To run the unittests:
5+
# python3 -m unittest discover -p generate_test_report.py
6+
7+
import argparse
8+
import unittest
9+
from io import StringIO
10+
from junitparser import JUnitXml, Failure
11+
from textwrap import dedent
12+
from subprocess import check_call
13+
14+
15+
def junit_from_xml(xml):
16+
return JUnitXml.fromfile(StringIO(xml))
17+
18+
19+
class TestReports(unittest.TestCase):
20+
def test_title_only(self):
21+
self.assertEqual(_generate_report("Foo", []), ("", None))
22+
23+
def test_no_tests_in_testsuite(self):
24+
self.assertEqual(
25+
_generate_report(
26+
"Foo",
27+
[
28+
junit_from_xml(
29+
dedent(
30+
"""\
31+
<?xml version="1.0" encoding="UTF-8"?>
32+
<testsuites time="0.00">
33+
<testsuite name="Empty" tests="0" failures="0" skipped="0" time="0.00">
34+
</testsuite>
35+
</testsuites>"""
36+
)
37+
)
38+
],
39+
),
40+
("", None),
41+
)
42+
43+
def test_no_failures(self):
44+
self.assertEqual(
45+
_generate_report(
46+
"Foo",
47+
[
48+
junit_from_xml(
49+
dedent(
50+
"""\
51+
<?xml version="1.0" encoding="UTF-8"?>
52+
<testsuites time="0.00">
53+
<testsuite name="Passed" tests="1" failures="0" skipped="0" time="0.00">
54+
<testcase classname="Bar/test_1" name="test_1" time="0.00"/>
55+
</testsuite>
56+
</testsuites>"""
57+
)
58+
)
59+
],
60+
),
61+
(
62+
dedent(
63+
"""\
64+
# Foo
65+
66+
* 1 test passed"""
67+
),
68+
"success",
69+
),
70+
)
71+
72+
def test_report_single_file_single_testsuite(self):
73+
self.assertEqual(
74+
_generate_report(
75+
"Foo",
76+
[
77+
junit_from_xml(
78+
dedent(
79+
"""\
80+
<?xml version="1.0" encoding="UTF-8"?>
81+
<testsuites time="8.89">
82+
<testsuite name="Bar" tests="4" failures="2" skipped="1" time="410.63">
83+
<testcase classname="Bar/test_1" name="test_1" time="0.02"/>
84+
<testcase classname="Bar/test_2" name="test_2" time="0.02">
85+
<skipped message="Reason"/>
86+
</testcase>
87+
<testcase classname="Bar/test_3" name="test_3" time="0.02">
88+
<failure><![CDATA[Output goes here]]></failure>
89+
</testcase>
90+
<testcase classname="Bar/test_4" name="test_4" time="0.02">
91+
<failure><![CDATA[Other output goes here]]></failure>
92+
</testcase>
93+
</testsuite>
94+
</testsuites>"""
95+
)
96+
)
97+
],
98+
),
99+
(
100+
dedent(
101+
"""\
102+
# Foo
103+
104+
* 1 test passed
105+
* 1 test skipped
106+
* 2 tests failed
107+
108+
## Failed tests
109+
(click to see output)
110+
111+
### Bar
112+
<details>
113+
<summary>Bar/test_3/test_3</summary>
114+
115+
```
116+
Output goes here
117+
```
118+
</details>
119+
<details>
120+
<summary>Bar/test_4/test_4</summary>
121+
122+
```
123+
Other output goes here
124+
```
125+
</details>"""
126+
),
127+
"error",
128+
),
129+
)
130+
131+
MULTI_SUITE_OUTPUT = (
132+
dedent(
133+
"""\
134+
# ABC and DEF
135+
136+
* 1 test passed
137+
* 1 test skipped
138+
* 2 tests failed
139+
140+
## Failed tests
141+
(click to see output)
142+
143+
### ABC
144+
<details>
145+
<summary>ABC/test_2/test_2</summary>
146+
147+
```
148+
ABC/test_2 output goes here
149+
```
150+
</details>
151+
152+
### DEF
153+
<details>
154+
<summary>DEF/test_2/test_2</summary>
155+
156+
```
157+
DEF/test_2 output goes here
158+
```
159+
</details>"""
160+
),
161+
"error",
162+
)
163+
164+
def test_report_single_file_multiple_testsuites(self):
165+
self.assertEqual(
166+
_generate_report(
167+
"ABC and DEF",
168+
[
169+
junit_from_xml(
170+
dedent(
171+
"""\
172+
<?xml version="1.0" encoding="UTF-8"?>
173+
<testsuites time="8.89">
174+
<testsuite name="ABC" tests="2" failures="1" skipped="0" time="410.63">
175+
<testcase classname="ABC/test_1" name="test_1" time="0.02"/>
176+
<testcase classname="ABC/test_2" name="test_2" time="0.02">
177+
<failure><![CDATA[ABC/test_2 output goes here]]></failure>
178+
</testcase>
179+
</testsuite>
180+
<testsuite name="DEF" tests="2" failures="1" skipped="1" time="410.63">
181+
<testcase classname="DEF/test_1" name="test_1" time="0.02">
182+
<skipped message="reason"/>
183+
</testcase>
184+
<testcase classname="DEF/test_2" name="test_2" time="0.02">
185+
<failure><![CDATA[DEF/test_2 output goes here]]></failure>
186+
</testcase>
187+
</testsuite>
188+
</testsuites>"""
189+
)
190+
)
191+
],
192+
),
193+
self.MULTI_SUITE_OUTPUT,
194+
)
195+
196+
def test_report_multiple_files_multiple_testsuites(self):
197+
self.assertEqual(
198+
_generate_report(
199+
"ABC and DEF",
200+
[
201+
junit_from_xml(
202+
dedent(
203+
"""\
204+
<?xml version="1.0" encoding="UTF-8"?>
205+
<testsuites time="8.89">
206+
<testsuite name="ABC" tests="2" failures="1" skipped="0" time="410.63">
207+
<testcase classname="ABC/test_1" name="test_1" time="0.02"/>
208+
<testcase classname="ABC/test_2" name="test_2" time="0.02">
209+
<failure><![CDATA[ABC/test_2 output goes here]]></failure>
210+
</testcase>
211+
</testsuite>
212+
</testsuites>"""
213+
)
214+
),
215+
junit_from_xml(
216+
dedent(
217+
"""\
218+
<?xml version="1.0" encoding="UTF-8"?>
219+
<testsuites time="8.89">
220+
<testsuite name="DEF" tests="2" failures="1" skipped="1" time="410.63">
221+
<testcase classname="DEF/test_1" name="test_1" time="0.02">
222+
<skipped message="reason"/>
223+
</testcase>
224+
<testcase classname="DEF/test_2" name="test_2" time="0.02">
225+
<failure><![CDATA[DEF/test_2 output goes here]]></failure>
226+
</testcase>
227+
</testsuite>
228+
</testsuites>"""
229+
)
230+
),
231+
],
232+
),
233+
self.MULTI_SUITE_OUTPUT,
234+
)
235+
236+
237+
def _generate_report(title, junit_objects):
238+
style = None
239+
240+
if not junit_objects:
241+
return ("", style)
242+
243+
failures = {}
244+
tests_run = 0
245+
tests_skipped = 0
246+
tests_failed = 0
247+
248+
for results in junit_objects:
249+
for testsuite in results:
250+
tests_run += testsuite.tests
251+
tests_skipped += testsuite.skipped
252+
tests_failed += testsuite.failures
253+
254+
for test in testsuite:
255+
if (
256+
not test.is_passed
257+
and test.result
258+
and isinstance(test.result[0], Failure)
259+
):
260+
if failures.get(testsuite.name) is None:
261+
failures[testsuite.name] = []
262+
failures[testsuite.name].append(
263+
(test.classname + "/" + test.name, test.result[0].text)
264+
)
265+
266+
if not tests_run:
267+
return ("", style)
268+
269+
style = "error" if tests_failed else "success"
270+
report = [f"# {title}", ""]
271+
272+
tests_passed = tests_run - tests_skipped - tests_failed
273+
274+
def plural(num_tests):
275+
return "test" if num_tests == 1 else "tests"
276+
277+
if tests_passed:
278+
report.append(f"* {tests_passed} {plural(tests_passed)} passed")
279+
if tests_skipped:
280+
report.append(f"* {tests_skipped} {plural(tests_skipped)} skipped")
281+
if tests_failed:
282+
report.append(f"* {tests_failed} {plural(tests_failed)} failed")
283+
284+
if failures:
285+
report.extend(["", "## Failed tests", "(click to see output)"])
286+
for testsuite_name, failures in failures.items():
287+
report.extend(["", f"### {testsuite_name}"])
288+
for name, output in failures:
289+
report.extend(
290+
[
291+
"<details>",
292+
f"<summary>{name}</summary>",
293+
"",
294+
"```",
295+
output,
296+
"```",
297+
"</details>",
298+
]
299+
)
300+
301+
return "\n".join(report), style
302+
303+
304+
def generate_report(title, junit_files):
305+
return _generate_report(title, [JUnitXml.fromfile(p) for p in junit_files])
306+
307+
308+
if __name__ == "__main__":
309+
parser = argparse.ArgumentParser()
310+
parser.add_argument(
311+
"title", help="Title of the test report, without Markdown formatting."
312+
)
313+
parser.add_argument("context", help="Annotation context to write to.")
314+
parser.add_argument("junit_files", help="Paths to JUnit report files.", nargs="*")
315+
args = parser.parse_args()
316+
317+
report, style = generate_report(args.title, args.junit_files)
318+
check_call(
319+
[
320+
"buildkite-agent",
321+
"annotate",
322+
"--context",
323+
args.context,
324+
"--style",
325+
style,
326+
report,
327+
]
328+
)

0 commit comments

Comments
 (0)