|
19 | 19 | import lit |
20 | 20 | import lit.formats |
21 | 21 | import lit.util |
| 22 | +import lit.Test |
22 | 23 |
|
| 24 | +# Like FLAKYPASS, but this one is a failure. |
| 25 | +FLAKYFAIL = lit.Test.ResultCode("FLAKYFAIL", "Flaky", True) |
23 | 26 |
|
24 | 27 | class SwiftTest(lit.formats.ShTest, object): |
25 | 28 | def __init__(self, coverage_mode=None, execute_external=True): |
@@ -53,7 +56,28 @@ def before_test(self, test, litConfig): |
53 | 56 | os.path.join(test.config.swift_test_results_dir, |
54 | 57 | "swift-%4m.profraw") |
55 | 58 |
|
| 59 | + # If long tests are not run, and this is not a test known to be quite |
| 60 | + # slow, tell Lit to re-run it at most 5 times upon failure to increase |
| 61 | + # our odds detecting non-determinism early. If a test turns out to |
| 62 | + # be flaky, it will fail and be reported as a FLAKYFAIL. |
| 63 | + # |
| 64 | + # NB: Unfortunately, we cannot base this condition on whether a |
| 65 | + # particular test is a long test without hacks because the test is not |
| 66 | + # parsed until it is executed. |
| 67 | + if ( |
| 68 | + "long_test" not in test.config.available_features |
| 69 | + # Some of these tests are notoriously slow. |
| 70 | + and not ("Interop" in test.path_in_suite and "Cxx" in test.path_in_suite) |
| 71 | + ): |
| 72 | + test.allowed_retries = 5 |
| 73 | + |
56 | 74 | def after_test(self, test, litConfig, result): |
| 75 | + # Intercept FLAKYPASS results and rewrite them into flaky failures. The |
| 76 | + # goal here is to catch non-determinism and complain about it rather |
| 77 | + # than to give a test more chances to succeed. |
| 78 | + if result.code == lit.Test.FLAKYPASS: |
| 79 | + result.code = FLAKYFAIL |
| 80 | + |
57 | 81 | if test.getSourcePath() in self.skipped_tests: |
58 | 82 | self.skipped_tests.remove(test.getSourcePath()) |
59 | 83 | return result |
|
0 commit comments