Skip to content

Commit ccffc2e

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. `max-retries-per-test/allow-retries-test_retry_attempts/test.py` was added but never used there. Now we're calling it. To correlate better between the test output and the test script I've used higher numbers of max allowed retries.
1 parent 3297340 commit ccffc2e

File tree

9 files changed

+87
-14
lines changed

9 files changed

+87
-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: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,9 @@ 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__(
155+
self, code, output="", elapsed=None, attempts=None, max_allowed_attempts=None
156+
):
155157
# The result code.
156158
self.code = code
157159
# The test output.
@@ -164,6 +166,10 @@ def __init__(self, code, output="", elapsed=None):
164166
self.metrics = {}
165167
# The micro-test results reported by this test.
166168
self.microResults = {}
169+
# How often was the test run?
170+
self.attempts = attempts
171+
# How many attempts were allowed for this test
172+
self.max_allowed_attempts = max_allowed_attempts
167173

168174
def addMetric(self, name, value):
169175
"""

llvm/utils/lit/lit/TestRunner.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2292,7 +2292,9 @@ 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(
2296+
status, output, attempts=i + 1, max_allowed_attempts=attempts
2297+
)
22962298

22972299

22982300
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: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,32 @@ 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 (
126+
test.result.max_allowed_attempts is not None
127+
and test.result.max_allowed_attempts > 1
128+
):
129+
extra_attrs.append(f"attempts={test.result.attempts}")
130+
extra_attrs.append(
131+
f"max_allowed_attempts={test.result.max_allowed_attempts}"
132+
)
133+
134+
if len(extra_attrs) > 0:
135+
extra_info = " [" + ",".join(extra_attrs) + "]"
136+
120137
print(
121-
"%s: %s (%d of %d)"
122-
% (test.result.code.name, test_name, self.completed, self.num_tests)
138+
"%s: %s (%d of %d)%s"
139+
% (
140+
test.result.code.name,
141+
test_name,
142+
self.completed,
143+
self.num_tests,
144+
extra_info,
145+
)
123146
)
124147

125148
# Show the test failure output, if requested.

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: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -72,49 +72,57 @@
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

0 commit comments

Comments
 (0)