Skip to content

Commit 216b896

Browse files
committed
Add migration notes.
1 parent 35fab76 commit 216b896

1 file changed

Lines changed: 63 additions & 11 deletions

File tree

  • randomizedtesting-jupiter/src/test/java/com/carrotsearch/randomizedtesting/jupiter
Lines changed: 63 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
# Feature: detecting tests that "leak" threads
1+
# Feature: detecting tests that "leak" threads
22

33
## Functionality
44

5-
* It should be possible to add a `@DetectThreadLeaks` extension which detects new threads forked within the test
6-
container. This extension takes a parameter - the scope of detection. Either we care about threads leaked
7-
from the entire container or from each individual test. Here is an example of use:
5+
* It should be possible to add a `@DetectThreadLeaks` extension which detects new threads forked within the test
6+
container. This extension takes a parameter - the scope of detection. Either we care about threads leaked
7+
from the entire container or from each individual test. Here is an example of use:
88

99
```java
1010

@@ -13,35 +13,87 @@ public class TestClass {
1313
@Test
1414
public void testMethod() {
1515
new Thread(() -> {
16-
try { Thread.sleep(1000); } catch (Exception e) {}
16+
try {
17+
Thread.sleep(1000);
18+
} catch (Exception e) {
19+
}
1720
}).start();
1821
}
1922
}
2023
```
2124

2225
* The extension is **only functional in sequential mode**. It should emit a warning and do nothing if tests are
23-
run in concurrent mode.
26+
run in concurrent mode.
2427

2528
* Occasionally there will be threads that cannot be joined but will eventually terminate. One can specify an additional
26-
"linger" time before the thread leak is reported, for example one second, below:
27-
29+
"linger" time before the thread leak is reported, for example one second, below:
30+
2831
```java
32+
2933
@DetectThreadLeaks(scope = DetectThreadLeaks.Scope.SUITE)
3034
@DetectThreadLeaks.LingerTime(millis = 1_000)
3135
public class TestClass {
3236
@Test
3337
public void testMethod() {
3438
new Thread(() -> {
35-
try { Thread.sleep(1000); } catch (Exception e) {}
39+
try {
40+
Thread.sleep(1000);
41+
} catch (Exception e) {
42+
}
3643
}).start();
3744
}
3845
}
3946
```
4047

4148
* In certain cases, system threads or other threads beyond the test's control may be started and cannot be terminated
42-
within the test's scope. The `@DetectThreadLeaks.ExcludeThreads` annotation can provide programmatic filters which
43-
tell the extension to ignore certain threads.
49+
within the test's scope. The `@DetectThreadLeaks.ExcludeThreads` annotation can provide programmatic filters which
50+
tell the extension to ignore certain threads.
51+
52+
* When `@DetectThreadLeaks` is active, it also detects **uncaught exceptions** thrown by any thread
53+
during the scope. Such exceptions are collected and reported as test failures. If both a thread leak and uncaught
54+
exceptions occur, all are reported: the leak error is thrown and the
55+
uncaught-exception errors are attached as suppressed exceptions.
56+
57+
```java
58+
59+
@DetectThreadLeaks(scope = DetectThreadLeaks.Scope.TEST)
60+
public class TestClass {
61+
@Test
62+
public void testMethod() throws InterruptedException {
63+
Thread t = new Thread(() -> {
64+
throw new RuntimeException("background failure");
65+
});
66+
t.start();
67+
t.join();
68+
}
69+
}
70+
```
4471

4572
## Migration notes (from randomizedtesting for junit4)
4673

74+
* `@ThreadLeakScope` is replaced with `@DetectThreadLeaks(scope = ...)`. The `NONE` scope
75+
(disabling all checks) has no equivalent; simply remove `@DetectThreadLeaks` from the class.
76+
The default scope changed: the old default was `TEST`; the new default is `SUITE`.
77+
78+
* `@ThreadLeakLingering(linger = N)` is replaced with `@DetectThreadLeaks.LingerTime(millis = N)`.
79+
The annotation can now be placed on individual test methods as well as on the class, with the
80+
method-level value taking precedence.
81+
82+
* `@ThreadLeakFilters(filters = {MyFilter.class})`: replace with
83+
`@DetectThreadLeaks.ExcludeThreads(MyFilter.class)`. The filter interface changed from
84+
`ThreadFilter.reject(Thread)` (return `true` to exclude) to `Predicate<Thread>.test(Thread)`
85+
(return `true` to exclude). Rename and invert the logic accordingly. The `defaultFilters`
86+
flag has no equivalent; built-in system-thread filters are always applied. Filters are now
87+
collected hierarchically from the method, the class, and all superclasses, and combined with OR.
88+
89+
* `@ThreadLeakAction`: interrupt-on-leak is now always performed as cleanup (no annotation
90+
needed). Leaked threads are interrupted and joined before the failure is reported. There is no
91+
equivalent of the `WARN`-only mode.
92+
93+
* `@ThreadLeakZombies`: zombie tracking (marking remaining tests as aborted when a leaked
94+
thread could not be killed) is not implemented. Threads that survive the interrupt/join budget
95+
are still reported in the failure message but subsequent tests are not skipped.
4796

97+
* `@ThreadLeakGroup` — the group scope (`ALL` / `MAIN` / `TESTGROUP`) is not configurable.
98+
The extension always uses `Thread.getAllStackTraces()`, equivalent to the old `ALL` group, and
99+
filters out known system threads automatically.

0 commit comments

Comments
 (0)