Skip to content

Commit 27c5ba3

Browse files
[𝘀𝗽𝗿] changes to main this commit is based on
Created using spr 1.3.6 [skip ci]
1 parent 536e414 commit 27c5ba3

File tree

2 files changed

+158
-0
lines changed

2 files changed

+158
-0
lines changed

.ci/generate_test_report_lib.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,57 @@
1212
"https://github.com/llvm/llvm-project/issues and add the "
1313
"`infrastructure` label."
1414
)
15+
# The maximum number of lines to pull from a ninja failure.
16+
NINJA_LOG_SIZE_THRESHOLD = 500
17+
18+
19+
def _parse_ninja_log(ninja_log: list[str]) -> list[tuple[str, str]]:
20+
"""Parses an individual ninja log."""
21+
failures = []
22+
index = 0
23+
while index < len(ninja_log):
24+
while index < len(ninja_log) and not ninja_log[index].startswith("FAILED:"):
25+
index += 1
26+
if index == len(ninja_log):
27+
# We hit the end of the log without finding a build failure, go to
28+
# the next log.
29+
return failures
30+
failing_action = ninja_log[index - 1].split("] ")[1]
31+
failure_log = []
32+
while (
33+
index < len(ninja_log)
34+
and not ninja_log[index].startswith("[")
35+
and not ninja_log[index].startswith(
36+
"ninja: build stopped: subcommand failed"
37+
)
38+
and len(failure_log) < NINJA_LOG_SIZE_THRESHOLD
39+
):
40+
failure_log.append(ninja_log[index])
41+
index += 1
42+
failures.append((failing_action, "\n".join(failure_log)))
43+
return failures
44+
45+
46+
def find_failure_in_ninja_logs(ninja_logs: list[list[str]]) -> list[tuple[str, str]]:
47+
"""Extracts failure messages from ninja output.
48+
49+
This patch takes stdout/stderr from ninja in the form of a list of files
50+
represented as a list of lines. This function then returns tuples containing
51+
the name of the target and the error message.
52+
53+
Args:
54+
ninja_logs: A list of files in the form of a list of lines representing the log
55+
files captured from ninja.
56+
57+
Returns:
58+
A list of tuples. The first string is the name of the target that failed. The
59+
second string is the error message.
60+
"""
61+
failures = []
62+
for ninja_log in ninja_logs:
63+
log_failures = _parse_ninja_log(ninja_log)
64+
failures.extend(log_failures)
65+
return failures
1566

1667

1768
# Set size_limit to limit the byte size of the report. The default is 1MB as this

.ci/generate_test_report_lib_test.py

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,113 @@ def junit_from_xml(xml):
1919

2020

2121
class TestReports(unittest.TestCase):
22+
def test_find_failure_ninja_logs(self):
23+
failures = generate_test_report_lib.find_failure_in_ninja_logs(
24+
[
25+
[
26+
"[1/5] test/1.stamp",
27+
"[2/5] test/2.stamp",
28+
"[3/5] test/3.stamp",
29+
"[4/5] test/4.stamp",
30+
"FAILED: test/4.stamp",
31+
"touch test/4.stamp",
32+
"Wow! This system is really broken!",
33+
"[5/5] test/5.stamp",
34+
],
35+
]
36+
)
37+
self.assertEqual(len(failures), 1)
38+
self.assertEqual(
39+
failures[0],
40+
(
41+
"test/4.stamp",
42+
dedent(
43+
"""\
44+
FAILED: test/4.stamp
45+
touch test/4.stamp
46+
Wow! This system is really broken!"""
47+
),
48+
),
49+
)
50+
51+
def test_no_failure_ninja_log(self):
52+
failures = generate_test_report_lib.find_failure_in_ninja_logs(
53+
[
54+
[
55+
"[1/3] test/1.stamp",
56+
"[2/3] test/2.stamp",
57+
"[3/3] test/3.stamp",
58+
]
59+
]
60+
)
61+
self.assertEqual(failures, [])
62+
63+
def test_ninja_log_end(self):
64+
failures = generate_test_report_lib.find_failure_in_ninja_logs(
65+
[
66+
[
67+
"[1/3] test/1.stamp",
68+
"[2/3] test/2.stamp",
69+
"[3/3] test/3.stamp",
70+
"FAILED: touch test/3.stamp",
71+
"Wow! This system is really broken!",
72+
"ninja: build stopped: subcommand failed.",
73+
]
74+
]
75+
)
76+
self.assertEqual(len(failures), 1)
77+
self.assertEqual(
78+
failures[0],
79+
(
80+
"test/3.stamp",
81+
dedent(
82+
"""\
83+
FAILED: touch test/3.stamp
84+
Wow! This system is really broken!"""
85+
),
86+
),
87+
)
88+
89+
def test_ninja_log_multiple_failures(self):
90+
failures = generate_test_report_lib.find_failure_in_ninja_logs(
91+
[
92+
[
93+
"[1/5] test/1.stamp",
94+
"[2/5] test/2.stamp",
95+
"FAILED: touch test/2.stamp",
96+
"Wow! This system is really broken!",
97+
"[3/5] test/3.stamp",
98+
"[4/5] test/4.stamp",
99+
"FAILED: touch test/4.stamp",
100+
"Wow! This system is maybe broken!",
101+
"[5/5] test/5.stamp",
102+
]
103+
]
104+
)
105+
self.assertEqual(len(failures), 2)
106+
self.assertEqual(
107+
failures[0],
108+
(
109+
"test/2.stamp",
110+
dedent(
111+
"""\
112+
FAILED: touch test/2.stamp
113+
Wow! This system is really broken!"""
114+
),
115+
),
116+
)
117+
self.assertEqual(
118+
failures[1],
119+
(
120+
"test/4.stamp",
121+
dedent(
122+
"""\
123+
FAILED: touch test/4.stamp
124+
Wow! This system is maybe broken!"""
125+
),
126+
),
127+
)
128+
22129
def test_title_only(self):
23130
self.assertEqual(
24131
generate_test_report_lib.generate_report("Foo", 0, []),

0 commit comments

Comments
 (0)