Skip to content

Commit 3468ef7

Browse files
authored
Merge branch 'llvm:main' into 2metrics
2 parents ee53a08 + 93d64a5 commit 3468ef7

File tree

12,808 files changed

+738938
-598020
lines changed

Some content is hidden

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

12,808 files changed

+738938
-598020
lines changed

.ci/all_requirements.txt

Lines changed: 192 additions & 2 deletions
Large diffs are not rendered by default.

.ci/generate_test_report_github.py

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,9 @@
44
"""Script to generate a build report for Github."""
55

66
import argparse
7-
import platform
87

98
import generate_test_report_lib
109

11-
def compute_platform_title() -> str:
12-
logo = ":window:" if platform.system() == "Windows" else ":penguin:"
13-
# On Linux the machine value is x86_64 on Windows it is AMD64.
14-
if platform.machine() == "x86_64" or platform.machine() == "AMD64":
15-
arch = "x64"
16-
else:
17-
arch = platform.machine()
18-
return f"{logo} {platform.system()} {arch} Test Results"
19-
2010

2111
if __name__ == "__main__":
2212
parser = argparse.ArgumentParser()
@@ -27,7 +17,9 @@ def compute_platform_title() -> str:
2717
args = parser.parse_args()
2818

2919
report = generate_test_report_lib.generate_report_from_files(
30-
compute_platform_title(), args.return_code, args.build_test_logs
20+
generate_test_report_lib.compute_platform_title(),
21+
args.return_code,
22+
args.build_test_logs,
3123
)
3224

3325
print(report)

.ci/generate_test_report_lib.py

Lines changed: 72 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,22 @@
33
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
44
"""Library to parse JUnit XML files and return a markdown report."""
55

6+
from typing import TypedDict, Optional
7+
import platform
8+
69
from junitparser import JUnitXml, Failure
710

11+
12+
# This data structure should match the definition in llvm-zorg in
13+
# premerge/advisor/advisor_lib.py
14+
# TODO(boomanaiden154): Drop the Optional here and switch to str | None when
15+
# we require Python 3.10.
16+
class FailureExplanation(TypedDict):
17+
name: str
18+
explained: bool
19+
reason: Optional[str]
20+
21+
822
SEE_BUILD_FILE_STR = "Download the build's log file to see the details."
923
UNRELATED_FAILURES_STR = (
1024
"If these failures are unrelated to your changes (for example "
@@ -48,6 +62,18 @@ def _parse_ninja_log(ninja_log: list[str]) -> list[tuple[str, str]]:
4862
# aligned with the failure.
4963
failing_action = ninja_log[index].split("FAILED: ")[1]
5064
failure_log = []
65+
66+
# Parse the lines above the FAILED: string if the line does not come
67+
# immediately after a progress indicator to ensure that we capture the
68+
# entire failure message.
69+
if not ninja_log[index - 1].startswith("["):
70+
before_index = index - 1
71+
while before_index > 0 and not ninja_log[before_index].startswith("["):
72+
failure_log.append(ninja_log[before_index])
73+
before_index = before_index - 1
74+
failure_log.reverse()
75+
76+
# Parse the failure information, which comes after the FAILED: tag.
5177
while (
5278
index < len(ninja_log)
5379
and not ninja_log[index].startswith("[")
@@ -82,16 +108,29 @@ def find_failure_in_ninja_logs(ninja_logs: list[list[str]]) -> list[tuple[str, s
82108
return failures
83109

84110

85-
def _format_ninja_failures(ninja_failures: list[tuple[str, str]]) -> list[str]:
86-
"""Formats ninja failures into summary views for the report."""
111+
def _format_failures(
112+
failures: list[tuple[str, str]], failure_explanations: dict[str, FailureExplanation]
113+
) -> list[str]:
114+
"""Formats failures into summary views for the report."""
87115
output = []
88-
for build_failure in ninja_failures:
116+
for build_failure in failures:
89117
failed_action, failure_message = build_failure
118+
failure_explanation = None
119+
if failed_action in failure_explanations:
120+
failure_explanation = failure_explanations[failed_action]
121+
output.append("<details>")
122+
if failure_explanation:
123+
output.extend(
124+
[
125+
f"<summary>{failed_action} (Likely Already Failing)</summary>" "",
126+
failure_explanation["reason"],
127+
"",
128+
]
129+
)
130+
else:
131+
output.extend([f"<summary>{failed_action}</summary>", ""])
90132
output.extend(
91133
[
92-
"<details>",
93-
f"<summary>{failed_action}</summary>",
94-
"",
95134
"```",
96135
failure_message,
97136
"```",
@@ -100,6 +139,7 @@ def _format_ninja_failures(ninja_failures: list[tuple[str, str]]) -> list[str]:
100139
)
101140
return output
102141

142+
103143
def get_failures(junit_objects) -> dict[str, list[tuple[str, str]]]:
104144
failures = {}
105145
for results in junit_objects:
@@ -131,12 +171,19 @@ def generate_report(
131171
ninja_logs: list[list[str]],
132172
size_limit=1024 * 1024,
133173
list_failures=True,
174+
failure_explanations_list: list[FailureExplanation] = [],
134175
):
135176
failures = get_failures(junit_objects)
136177
tests_run = 0
137178
tests_skipped = 0
138179
tests_failed = 0
139180

181+
failure_explanations: dict[str, FailureExplanation] = {}
182+
for failure_explanation in failure_explanations_list:
183+
if not failure_explanation["explained"]:
184+
continue
185+
failure_explanations[failure_explanation["name"]] = failure_explanation
186+
140187
for results in junit_objects:
141188
for testsuite in results:
142189
tests_run += testsuite.tests
@@ -149,8 +196,8 @@ def generate_report(
149196
if return_code == 0:
150197
report.extend(
151198
[
152-
"The build succeeded and no tests ran. This is expected in some "
153-
"build configurations."
199+
":white_check_mark: The build succeeded and no tests ran. "
200+
"This is expected in some build configurations."
154201
]
155202
)
156203
else:
@@ -175,7 +222,7 @@ def generate_report(
175222
"",
176223
]
177224
)
178-
report.extend(_format_ninja_failures(ninja_failures))
225+
report.extend(_format_failures(ninja_failures, failure_explanations))
179226
report.extend(
180227
[
181228
"",
@@ -211,18 +258,7 @@ def plural(num_tests):
211258

212259
for testsuite_name, failures in failures.items():
213260
report.extend(["", f"### {testsuite_name}"])
214-
for name, output in failures:
215-
report.extend(
216-
[
217-
"<details>",
218-
f"<summary>{name}</summary>",
219-
"",
220-
"```",
221-
output,
222-
"```",
223-
"</details>",
224-
]
225-
)
261+
report.extend(_format_failures(failures, failure_explanations))
226262
elif return_code != 0:
227263
# No tests failed but the build was in a failed state. Bring this to the user's
228264
# attention.
@@ -247,7 +283,11 @@ def plural(num_tests):
247283
"",
248284
]
249285
)
250-
report.extend(_format_ninja_failures(ninja_failures))
286+
report.extend(_format_failures(ninja_failures, failure_explanations))
287+
else:
288+
report.extend(
289+
["", ":white_check_mark: The build succeeded and all tests passed."]
290+
)
251291

252292
if failures or return_code != 0:
253293
report.extend(["", UNRELATED_FAILURES_STR])
@@ -284,3 +324,13 @@ def load_info_from_files(build_log_files):
284324
def generate_report_from_files(title, return_code, build_log_files):
285325
junit_objects, ninja_logs = load_info_from_files(build_log_files)
286326
return generate_report(title, return_code, junit_objects, ninja_logs)
327+
328+
329+
def compute_platform_title() -> str:
330+
logo = ":window:" if platform.system() == "Windows" else ":penguin:"
331+
# On Linux the machine value is x86_64 on Windows it is AMD64.
332+
if platform.machine() == "x86_64" or platform.machine() == "AMD64":
333+
arch = "x64"
334+
else:
335+
arch = platform.machine()
336+
return f"{logo} {platform.system()} {arch} Test Results"

.ci/generate_test_report_lib_test.py

Lines changed: 159 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ def test_ninja_log_mismatched_failed(self):
181181
"tools/check-langley",
182182
dedent(
183183
"""\
184+
ModuleNotFoundError: No module named 'mount_langley'
184185
FAILED: tools/check-langley
185186
Wow! This system is really broken!"""
186187
),
@@ -194,7 +195,7 @@ def test_title_only(self):
194195
"""\
195196
# Foo
196197
197-
The build succeeded and no tests ran. This is expected in some build configurations."""
198+
:white_check_mark: The build succeeded and no tests ran. This is expected in some build configurations."""
198199
),
199200
)
200201

@@ -308,7 +309,9 @@ def test_no_failures(self):
308309
"""\
309310
# Foo
310311
311-
* 1 test passed"""
312+
* 1 test passed
313+
314+
:white_check_mark: The build succeeded and all tests passed."""
312315
)
313316
),
314317
)
@@ -781,6 +784,160 @@ def test_report_size_limit(self):
781784
),
782785
)
783786

787+
def test_report_ninja_explanation(self):
788+
self.assertEqual(
789+
generate_test_report_lib.generate_report(
790+
"Foo",
791+
1,
792+
[],
793+
[
794+
[
795+
"[1/5] test/1.stamp",
796+
"[2/5] test/2.stamp",
797+
"[3/5] test/3.stamp",
798+
"[4/5] test/4.stamp",
799+
"FAILED: test/4.stamp",
800+
"touch test/4.stamp",
801+
"Half Moon Bay.",
802+
"[5/5] test/5.stamp",
803+
]
804+
],
805+
failure_explanations_list=[
806+
{
807+
"name": "test/4.stamp",
808+
"explained": True,
809+
"reason": "Failing at head",
810+
}
811+
],
812+
),
813+
dedent(
814+
"""\
815+
# Foo
816+
817+
The build failed before running any tests. Click on a failure below to see the details.
818+
819+
<details>
820+
<summary>test/4.stamp (Likely Already Failing)</summary>
821+
Failing at head
822+
823+
```
824+
FAILED: test/4.stamp
825+
touch test/4.stamp
826+
Half Moon Bay.
827+
```
828+
</details>
829+
830+
If these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the `infrastructure` label."""
831+
),
832+
)
833+
834+
def test_report_test_failure_explanation(self):
835+
self.assertEqual(
836+
generate_test_report_lib.generate_report(
837+
"Foo",
838+
1,
839+
[
840+
junit_from_xml(
841+
dedent(
842+
"""\
843+
<?xml version="1.0" encoding="UTF-8"?>
844+
<testsuites time="8.89">
845+
<testsuite name="Bar" tests="1" failures="1" skipped="0" time="410.63">
846+
<testcase classname="Bar/test_3" name="test_3" time="0.02">
847+
<failure><![CDATA[Error! Expected Big Sur to be next to the ocean.]]></failure>
848+
</testcase>
849+
</testsuite>
850+
</testsuites>"""
851+
)
852+
)
853+
],
854+
[],
855+
failure_explanations_list=[
856+
{
857+
"name": "Bar/test_3/test_3",
858+
"explained": True,
859+
"reason": "Big Sur is next to the Pacific.",
860+
}
861+
],
862+
),
863+
(
864+
dedent(
865+
"""\
866+
# Foo
867+
868+
* 1 test failed
869+
870+
## Failed Tests
871+
(click on a test name to see its output)
872+
873+
### Bar
874+
<details>
875+
<summary>Bar/test_3/test_3 (Likely Already Failing)</summary>
876+
Big Sur is next to the Pacific.
877+
878+
```
879+
Error! Expected Big Sur to be next to the ocean.
880+
```
881+
</details>
882+
883+
If these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the `infrastructure` label."""
884+
)
885+
),
886+
)
887+
888+
def test_report_test_failure_have_explanation_explained_false(self):
889+
self.assertEqual(
890+
generate_test_report_lib.generate_report(
891+
"Foo",
892+
1,
893+
[
894+
junit_from_xml(
895+
dedent(
896+
"""\
897+
<?xml version="1.0" encoding="UTF-8"?>
898+
<testsuites time="8.89">
899+
<testsuite name="Bar" tests="1" failures="1" skipped="0" time="410.63">
900+
<testcase classname="Bar/test_3" name="test_3" time="0.02">
901+
<failure><![CDATA[Error! Expected Mt. Shasta to be next in the Eastern Sierras.]]></failure>
902+
</testcase>
903+
</testsuite>
904+
</testsuites>"""
905+
)
906+
)
907+
],
908+
[],
909+
failure_explanations_list=[
910+
{
911+
"name": "Bar/test_3/test_3",
912+
"explained": False,
913+
"reason": "Mt. Shasta is in the Cascades",
914+
}
915+
],
916+
),
917+
(
918+
dedent(
919+
"""\
920+
# Foo
921+
922+
* 1 test failed
923+
924+
## Failed Tests
925+
(click on a test name to see its output)
926+
927+
### Bar
928+
<details>
929+
<summary>Bar/test_3/test_3</summary>
930+
931+
```
932+
Error! Expected Mt. Shasta to be next in the Eastern Sierras.
933+
```
934+
</details>
935+
936+
If these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the `infrastructure` label."""
937+
)
938+
),
939+
)
940+
784941
def test_generate_report_end_to_end(self):
785942
with tempfile.TemporaryDirectory() as temp_dir:
786943
junit_xml_file = os.path.join(temp_dir, "junit.xml")

0 commit comments

Comments
 (0)