Skip to content

Commit 26f5f34

Browse files
committed
[llvm][llvm-lit] Add option to create unique result file names if results already exist
When running a build like: ninja check-clang check-llvm Prior to my changes you ended up with one results file, in this specific case Junit XML: results.xml This would only include the last set of tests lit ran, which were for llvm. To get around this, many CI systems will run one check target, move the file away, then run another. for target in targets: ninja target mv results.xml results-${target}.xml I want to use something like this Buildkite reporting plugin in CI, which needs to have all the results available: https://buildkite.com/docs/agent/v3/cli-annotate#using-annotations-to-report-test-results Modifying CI's build scripts for Windows and Linux is a lot of work. So my changes instead make lit detect an existing result file and modify the file name until it finds a unique file name to write to. Now you will get: results.xml results.1.xml This will work for all result file types since I'm doing it in the base Report class. Now you've got separate files, it's easy to collect them with `<path>/*.xml`. The number will increment as many times as needed until a useable name is found.
1 parent f212fda commit 26f5f34

File tree

3 files changed

+72
-10
lines changed

3 files changed

+72
-10
lines changed

llvm/utils/lit/lit/cl_arguments.py

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,13 @@ def parse_args():
175175
type=lit.reports.TimeTraceReport,
176176
help="Write Chrome tracing compatible JSON to the specified file",
177177
)
178+
execution_group.add_argument(
179+
"--use-unique-output-file-name",
180+
help="When enabled, lit will not overwrite existing test report files. "
181+
"Instead it will modify the file name until it finds a file name "
182+
"that does not already exist. [Default: Off]",
183+
action="store_true",
184+
)
178185
execution_group.add_argument(
179186
"--timeout",
180187
dest="maxIndividualTestTime",
@@ -332,16 +339,21 @@ def parse_args():
332339
else:
333340
opts.shard = None
334341

335-
opts.reports = filter(
336-
None,
337-
[
338-
opts.output,
339-
opts.xunit_xml_output,
340-
opts.resultdb_output,
341-
opts.time_trace_output,
342-
],
342+
opts.reports = list(
343+
filter(
344+
None,
345+
[
346+
opts.output,
347+
opts.xunit_xml_output,
348+
opts.resultdb_output,
349+
opts.time_trace_output,
350+
],
351+
)
343352
)
344353

354+
for report in opts.reports:
355+
report.use_unique_output_file_name = opts.use_unique_output_file_name
356+
345357
return opts
346358

347359

llvm/utils/lit/lit/reports.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import datetime
44
import itertools
55
import json
6+
import os
67

78
from xml.sax.saxutils import quoteattr as quo
89

@@ -18,10 +19,31 @@ def by_suite_and_test_path(test):
1819
class Report(object):
1920
def __init__(self, output_file):
2021
self.output_file = output_file
22+
# Set by the option parser later.
23+
self.use_unique_output_file_name = False
2124

2225
def write_results(self, tests, elapsed):
23-
with open(self.output_file, "w") as file:
24-
self._write_results_to_file(tests, elapsed, file)
26+
if self.use_unique_output_file_name:
27+
file = None
28+
filepath = self.output_file
29+
attempt = 0
30+
while file is None:
31+
try:
32+
file = open(filepath, "x")
33+
except FileExistsError:
34+
attempt += 1
35+
# If there is an extension insert before that because most
36+
# glob patterns for these will be '*.extension'. Otherwise
37+
# add to the end of the path.
38+
path, ext = os.path.splitext(self.output_file)
39+
filepath = path + f".{attempt}" + ext
40+
41+
with file:
42+
self._write_results_to_file(tests, elapsed, file)
43+
else:
44+
# Overwrite if the results already exist.
45+
with open(self.output_file, "w") as file:
46+
self._write_results_to_file(tests, elapsed, file)
2547

2648
@abc.abstractmethod
2749
def _write_results_to_file(self, tests, elapsed, file):
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Check that lit will not overwrite existing result files when given
2+
# --use-unique-output-file-name.
3+
4+
# Files are overwritten without the option.
5+
# RUN: rm -rf %t.xunit*.xml
6+
# RUN: echo "test" > %t.xunit.xml
7+
# RUN: not %{lit} --xunit-xml-output %t.xunit.xml %{inputs}/xunit-output
8+
# RUN: FileCheck < %t.xunit.xml %s --check-prefix=NEW
9+
10+
# RUN: rm -rf %t.xunit*.xml
11+
# RUN: echo "test" > %t.xunit.xml
12+
# Files should not be overwritten with the option.
13+
# RUN: not %{lit} --xunit-xml-output %t.xunit.xml --use-unique-output-file-name %{inputs}/xunit-output
14+
# RUN: FileCheck < %t.xunit.xml %s --check-prefix=EXISTING
15+
# EXISTING: test
16+
# Results in a new file with "1" added.
17+
# RUN: FileCheck < %t.xunit.1.xml %s --check-prefix=NEW
18+
# NEW: <?xml version="1.0" encoding="UTF-8"?>
19+
# NEW-NEXT: <testsuites time="{{[0-9.]+}}">
20+
# (assuming that other tests check the whole contents of the file)
21+
22+
# The number should increment as many times as needed.
23+
# RUN: touch %t.xunit.2.xml
24+
# RUN: touch %t.xunit.3.xml
25+
# RUN: touch %t.xunit.4.xml
26+
27+
# RUN: not %{lit} --xunit-xml-output %t.xunit.xml --use-unique-output-file-name %{inputs}/xunit-output
28+
# RUN: FileCheck < %t.xunit.5.xml %s --check-prefix=NEW

0 commit comments

Comments
 (0)