Skip to content

Commit 2984d3a

Browse files
committed
[lit] introduce --show-attempts-count
This introduces `--show-attempts-count` output option to `lit`. It shows the number of attempts needed for a test to pass. It also shows the maximum number of attempts that were allowed for this test. This option is useful when you want to understand how many attempts took for a flaky test (``FLAKYPASS``) to pass. This is how the test output looks like *without* `--show-attempts-count`: ``` PASS: your-test-suite :: your-first-test.py (1 of 3) FLAKYPASS: your-test-suite :: your-second-test.py (2 of 2) ``` This is the output *with* `--show-attempts-count`: ``` PASS: your-test-suite :: your-first-test.py (1 of 2) FLAKYPASS: your-test-suite :: your-second-test.py (2 of 2) [attempts=3,max_allowed_attempts=4] ``` In this case `your-second-test.py` was executed three times and it succeeded after the third time (`attempts=3`). Technically another run would have been possible (`max_allowed_attempts=4`). We will only append the extra information when a test was allowed more than one attempt to succeed (i.e. see :option:`--max-retries-per-test`). NOTE: Additionally this is a fixup for #141851 where the tests were not quite right. To correlate better between the test output and the test script I've used higher numbers of max allowed retries.
1 parent 3297340 commit 2984d3a

File tree

9 files changed

+74
-14
lines changed

9 files changed

+74
-14
lines changed

llvm/docs/CommandGuide/lit.rst

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,34 @@ OUTPUT OPTIONS
144144

145145
Show expectedly failed tests.
146146

147+
.. option:: --show-attempts-count
148+
149+
Show the number of attempts needed for a test to pass. It also shows the
150+
maximum number of attempts that were allowed for this test. This option is
151+
useful when you want to understand how many attempts took for a flaky test
152+
(``FLAKYPASS``) to pass.
153+
154+
This is how the test output looks like *without* :option:`--show-attempts-count`
155+
156+
.. code-block:: none
157+
158+
PASS: your-test-suite :: your-first-test.py (1 of 3)
159+
FLAKYPASS: your-test-suite :: your-second-test.py (2 of 2)
160+
161+
This is the output *with* :option:`--show-attempts-count`
162+
163+
.. code-block:: none
164+
165+
PASS: your-test-suite :: your-first-test.py (1 of 2)
166+
FLAKYPASS: your-test-suite :: your-second-test.py (2 of 2) [attempts=3,max_allowed_attempts=4]
167+
168+
In this case ``your-second-test.py`` was executed three times and it succeeded
169+
after the third time (``attempts=3``). Technically another run would have been
170+
possible (``max_allowed_attempts=4``).
171+
172+
We will only append the extra information when a test was allowed more than one
173+
attempt to succeed (i.e. see :option:`--max-retries-per-test`).
174+
147175
.. _execution-options:
148176

149177
EXECUTION OPTIONS

llvm/utils/lit/lit/Test.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ def toMetricValue(value):
151151
class Result(object):
152152
"""Wrapper for the results of executing an individual test."""
153153

154-
def __init__(self, code, output="", elapsed=None):
154+
def __init__(self, code, output="", elapsed=None, attempts=None, max_allowed_attempts=None):
155155
# The result code.
156156
self.code = code
157157
# The test output.
@@ -164,6 +164,10 @@ def __init__(self, code, output="", elapsed=None):
164164
self.metrics = {}
165165
# The micro-test results reported by this test.
166166
self.microResults = {}
167+
# How often was the test run?
168+
self.attempts = attempts
169+
# How many attempts were allowed for this test
170+
self.max_allowed_attempts = max_allowed_attempts
167171

168172
def addMetric(self, name, value):
169173
"""

llvm/utils/lit/lit/TestRunner.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2292,7 +2292,7 @@ def runOnce(
22922292
if err:
22932293
output += """Command Output (stderr):\n--\n%s\n--\n""" % (err,)
22942294

2295-
return lit.Test.Result(status, output)
2295+
return lit.Test.Result(status, output, attempts=i+1, max_allowed_attempts=attempts)
22962296

22972297

22982298
def executeShTest(

llvm/utils/lit/lit/cl_arguments.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,12 @@ def parse_args():
104104
help="Do not use curses based progress bar",
105105
action="store_false",
106106
)
107+
format_group.add_argument(
108+
"--show-attempts-count",
109+
dest="showAttemptsCount",
110+
help="Show number of attempts and maximum attempts for flaky tests.",
111+
action="store_true",
112+
)
107113

108114
# Note: this does not generate flags for user-defined result codes.
109115
success_codes = [c for c in lit.Test.ResultCode.all_codes() if not c.isFailure]

llvm/utils/lit/lit/display.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,10 +117,23 @@ def clear(self, interrupted):
117117
def print_result(self, test):
118118
# Show the test result line.
119119
test_name = test.getFullName()
120+
121+
extra_info = ""
122+
extra_attrs = []
123+
124+
if self.opts.showAttemptsCount:
125+
if test.result.max_allowed_attempts is not None and test.result.max_allowed_attempts > 1:
126+
extra_attrs.append(f"attempts={test.result.attempts}")
127+
extra_attrs.append(f"max_allowed_attempts={test.result.max_allowed_attempts}")
128+
129+
if len(extra_attrs) > 0:
130+
extra_info = " [" + ",".join(extra_attrs) + "]"
131+
120132
print(
121-
"%s: %s (%d of %d)"
122-
% (test.result.code.name, test_name, self.completed, self.num_tests)
133+
"%s: %s (%d of %d)%s"
134+
% (test.result.code.name, test_name, self.completed, self.num_tests, extra_info)
123135
)
136+
124137

125138
# Show the test failure output, if requested.
126139
if (test.isFailure() and self.opts.showOutput) or self.opts.showAllOutput:

llvm/utils/lit/tests/Inputs/max-retries-per-test/allow-retries-no-test_retry_attempts/test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# ALLOW_RETRIES: 3
1+
# ALLOW_RETRIES: 8
22
# RUN: "%python" "%s" "%counter"
33

44
import sys

llvm/utils/lit/tests/Inputs/max-retries-per-test/allow-retries-test_retry_attempts/test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# ALLOW_RETRIES: 3
1+
# ALLOW_RETRIES: 10
22
# RUN: "%python" "%s" "%counter"
33

44
import sys

llvm/utils/lit/tests/Inputs/max-retries-per-test/no-allow-retries-test_retry_attempts/lit.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ config.test_exec_root = None
99
config.substitutions.append(("%python", lit_config.params.get("python", "")))
1010
config.substitutions.append(("%counter", lit_config.params.get("counter", "")))
1111

12-
config.test_retry_attempts = 3
12+
config.test_retry_attempts = 9

llvm/utils/lit/tests/allow-retries.py

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -72,49 +72,58 @@
7272
# CHECK-TEST7: Passed With Retry: 1
7373

7474
# This test only passes on the 4th try. Here we check that a test can be re-run when:
75-
# * The "--max-retries-per-test" is specified high enough (3).
75+
# * The "--max-retries-per-test" is specified high enough (7).
7676
# * No ALLOW_RETRIES keyword is used in the test script.
7777
# * No config.test_retry_attempts is adjusted in the test suite config file.
7878
# RUN: rm -f %t.counter
7979
# RUN: %{lit} %{inputs}/max-retries-per-test/no-allow-retries-no-test_retry_attempts/test.py \
80-
# RUN: --max-retries-per-test=3 \
80+
# RUN: --max-retries-per-test=7 \
81+
# RUN: --show-attempts-count \
8182
# RUN: -Dcounter=%t.counter \
8283
# RUN: -Dpython=%{python} \
8384
# RUN: | FileCheck --check-prefix=CHECK-TEST8 %s
85+
# CHECK-TEST8: FLAKYPASS: no-allow-retries-no-test_retry_attempts :: test.py (1 of 1) [attempts=4,max_allowed_attempts=8]
8486
# CHECK-TEST8: Passed With Retry: 1
8587

8688
# This test only passes on the 4th try. Here we check that a test can be re-run when:
8789
# * The "--max-retries-per-test" is specified too low (2).
88-
# * ALLOW_RETRIES is specified high enough (3)
90+
# * ALLOW_RETRIES is specified high enough (8)
8991
# * No config.test_retry_attempts is adjusted in the test suite config file.
9092
# RUN: rm -f %t.counter
9193
# RUN: %{lit} %{inputs}/max-retries-per-test/allow-retries-no-test_retry_attempts/test.py \
9294
# RUN: --max-retries-per-test=2 \
95+
# RUN: --show-attempts-count \
9396
# RUN: -Dcounter=%t.counter \
9497
# RUN: -Dpython=%{python} \
9598
# RUN: | FileCheck --check-prefix=CHECK-TEST9 %s
99+
# CHECK-TEST9: FLAKYPASS: allow-retries-no-test_retry_attempts :: test.py (1 of 1) [attempts=4,max_allowed_attempts=9]
96100
# CHECK-TEST9: Passed With Retry: 1
97101

98102
# This test only passes on the 4th try. Here we check that a test can be re-run when:
99103
# * The "--max-retries-per-test" is specified too low (2).
100104
# * No ALLOW_RETRIES keyword is used in the test script.
101-
# * config.test_retry_attempts is set high enough (3).
105+
# * config.test_retry_attempts is set high enough (9).
102106
# RUN: rm -f %t.counter
103107
# RUN: %{lit} %{inputs}/max-retries-per-test/no-allow-retries-test_retry_attempts/test.py \
104108
# RUN: --max-retries-per-test=2 \
109+
# RUN: --show-attempts-count \
105110
# RUN: -Dcounter=%t.counter \
106111
# RUN: -Dpython=%{python} \
107112
# RUN: | FileCheck --check-prefix=CHECK-TEST10 %s
113+
# CHECK-TEST10: FLAKYPASS: no-allow-retries-test_retry_attempts :: test.py (1 of 1) [attempts=4,max_allowed_attempts=10]
108114
# CHECK-TEST10: Passed With Retry: 1
109115

110116
# This test only passes on the 4th try. Here we check that a test can be re-run when:
111117
# * The "--max-retries-per-test" is specified too low (1).
112-
# * ALLOW_RETRIES keyword set high enough (3).
113-
# * config.test_retry_attempts is set too low enough (2).
118+
# * ALLOW_RETRIES keyword is set high enough (10)
119+
# * config.test_retry_attempts is set too low (2).
114120
# RUN: rm -f %t.counter
115-
# RUN: %{lit} %{inputs}/max-retries-per-test/no-allow-retries-test_retry_attempts/test.py \
121+
# RUN: %{lit} %{inputs}/max-retries-per-test/allow-retries-test_retry_attempts/test.py \
116122
# RUN: --max-retries-per-test=1 \
123+
# RUN: --show-attempts-count \
117124
# RUN: -Dcounter=%t.counter \
118125
# RUN: -Dpython=%{python} \
119126
# RUN: | FileCheck --check-prefix=CHECK-TEST11 %s
127+
# CHECK-TEST11: FLAKYPASS: allow-retries-test_retry_attempts :: test.py (1 of 1) [attempts=4,max_allowed_attempts=11]
120128
# CHECK-TEST11: Passed With Retry: 1
129+

0 commit comments

Comments
 (0)