Skip to content

Commit 2cccb29

Browse files
committed
Enable NullAway in tests
1 parent 5587851 commit 2cccb29

File tree

131 files changed

+779
-312
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

131 files changed

+779
-312
lines changed

gradle/plugins/common/src/main/kotlin/junitbuild.java-nullability-conventions.gradle.kts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,14 @@ tasks.withType<JavaCompile>().configureEach {
2929
tasks.compileTestJava {
3030
options.errorprone.nullaway {
3131
handleTestAssertionLibraries = true
32+
excludedFieldAnnotations.addAll(
33+
"org.junit.jupiter.api.io.TempDir",
34+
"org.junit.jupiter.params.Parameter",
35+
"org.junit.runners.Parameterized.Parameter",
36+
"org.mockito.Captor",
37+
"org.mockito.InjectMocks",
38+
"org.mockito.Mock",
39+
"org.mockito.Spy",
40+
)
3241
}
3342
}

jupiter-tests/jupiter-tests.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import org.gradle.api.tasks.PathSensitivity.RELATIVE
22

33
plugins {
44
id("junitbuild.code-generator")
5+
id("junitbuild.java-nullability-conventions")
56
id("junitbuild.kotlin-library-conventions")
67
id("junitbuild.junit4-compatibility")
78
id("junitbuild.testing-conventions")

jupiter-tests/src/test/java/org/junit/jupiter/api/AssertAllAssertionsTests.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,31 +38,37 @@
3838
*/
3939
class AssertAllAssertionsTests {
4040

41+
@SuppressWarnings({ "DataFlowIssue", "NullAway" })
4142
@Test
4243
void assertAllWithNullExecutableArray() {
4344
assertPrecondition("executables array must not be null or empty", () -> assertAll((Executable[]) null));
4445
}
4546

47+
@SuppressWarnings({ "DataFlowIssue", "NullAway" })
4648
@Test
4749
void assertAllWithNullExecutableCollection() {
4850
assertPrecondition("executables collection must not be null", () -> assertAll((Collection<Executable>) null));
4951
}
5052

53+
@SuppressWarnings({ "DataFlowIssue", "NullAway" })
5154
@Test
5255
void assertAllWithNullExecutableStream() {
5356
assertPrecondition("executables stream must not be null", () -> assertAll((Stream<Executable>) null));
5457
}
5558

59+
@SuppressWarnings({ "DataFlowIssue", "NullAway" })
5660
@Test
5761
void assertAllWithNullInExecutableArray() {
5862
assertPrecondition("individual executables must not be null", () -> assertAll((Executable) null));
5963
}
6064

65+
@SuppressWarnings({ "NullAway" })
6166
@Test
6267
void assertAllWithNullInExecutableCollection() {
6368
assertPrecondition("individual executables must not be null", () -> assertAll(asList((Executable) null)));
6469
}
6570

71+
@SuppressWarnings({ "DataFlowIssue", "NullAway" })
6672
@Test
6773
void assertAllWithNullInExecutableStream() {
6874
assertPrecondition("individual executables must not be null", () -> assertAll(Stream.of((Executable) null)));

jupiter-tests/src/test/java/org/junit/jupiter/api/AssertInstanceOfAssertionsTests.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import java.io.IOException;
1919

20+
import org.jspecify.annotations.Nullable;
2021
import org.junit.jupiter.api.function.Executable;
2122
import org.opentest4j.AssertionFailedError;
2223

@@ -91,7 +92,7 @@ private <T> void assertInstanceOfSucceeds(Class<T> expectedType, Object actualVa
9192
assertSame(res, actualValue);
9293
}
9394

94-
private void assertInstanceOfFails(Class<?> expectedType, Object actualValue, String unexpectedSort) {
95+
private void assertInstanceOfFails(Class<?> expectedType, @Nullable Object actualValue, String unexpectedSort) {
9596
String valueType = actualValue == null ? "null" : actualValue.getClass().getCanonicalName();
9697
String expectedMessage = "Unexpected %s, expected: <%s> but was: <%s>".formatted(unexpectedSort,
9798
expectedType.getCanonicalName(), valueType);

jupiter-tests/src/test/java/org/junit/jupiter/api/AssertLinesMatchAssertionsTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ void assertLinesMatchUsingFastForwardMarkerWithLimit3() {
9595
}
9696

9797
@Test
98-
@SuppressWarnings({ "unchecked", "rawtypes" })
98+
@SuppressWarnings({ "unchecked", "rawtypes", "DataFlowIssue", "NullAway" })
9999
void assertLinesMatchWithNullFails() {
100100
assertThrows(PreconditionViolationException.class, () -> assertLinesMatch(null, (List) null));
101101
assertThrows(PreconditionViolationException.class, () -> assertLinesMatch(null, Collections.emptyList()));

jupiter-tests/src/test/java/org/junit/jupiter/api/AssertNullAssertionsTests.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
import java.util.function.Supplier;
2020

21+
import org.jspecify.annotations.NullUnmarked;
22+
import org.jspecify.annotations.Nullable;
2123
import org.opentest4j.AssertionFailedError;
2224

2325
/**
@@ -63,7 +65,8 @@ void assertNullWithNonNullObjectWithNullStringReturnedFromToStringAndMessageSupp
6365
}
6466

6567
@SuppressWarnings("unused")
66-
private void assertNullWithNonNullObjectWithNullStringReturnedFromToString(Supplier<String> messageSupplier) {
68+
private void assertNullWithNonNullObjectWithNullStringReturnedFromToString(
69+
@Nullable Supplier<String> messageSupplier) {
6770
String actual = "null";
6871
try {
6972
if (messageSupplier == null) {
@@ -94,7 +97,8 @@ void assertNullWithNonNullObjectWithNullReferenceReturnedFromToStringAndMessageS
9497
}
9598

9699
@SuppressWarnings("unused")
97-
private void assertNullWithNonNullObjectWithNullReferenceReturnedFromToString(Supplier<String> messageSupplier) {
100+
private void assertNullWithNonNullObjectWithNullReferenceReturnedFromToString(
101+
@Nullable Supplier<String> messageSupplier) {
98102
Object actual = new NullToString();
99103
try {
100104
if (messageSupplier == null) {
@@ -141,6 +145,7 @@ void assertNullWithNonNullObjectAndMessageSupplier() {
141145
}
142146
}
143147

148+
@NullUnmarked
144149
private static class NullToString {
145150

146151
@Override

jupiter-tests/src/test/java/org/junit/jupiter/api/AssertThrowsAssertionsTests.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ void assertThrowsWithMethodReferenceForNonVoidReturnType() {
4747
future.run();
4848

4949
ExecutionException exception = assertThrows(ExecutionException.class, future::get);
50+
assertNotNull(exception.getCause());
5051
assertEquals("boom", exception.getCause().getMessage());
5152
}
5253

jupiter-tests/src/test/java/org/junit/jupiter/api/AssertThrowsExactlyAssertionsTests.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ void assertThrowsWithMethodReferenceForNonVoidReturnType() {
8787
future.run();
8888

8989
ExecutionException exception = assertThrowsExactly(ExecutionException.class, future::get);
90+
assertNotNull(exception.getCause());
9091
assertEquals("boom", exception.getCause().getMessage());
9192
}
9293

jupiter-tests/src/test/java/org/junit/jupiter/api/AssertTimeoutPreemptivelyAssertionsTests.java

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
import static org.junit.jupiter.api.Assertions.assertFalse;
1919
import static org.junit.jupiter.api.Assertions.assertThrows;
2020
import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively;
21-
import static org.junit.jupiter.api.Assertions.assertTrue;
2221
import static org.junit.jupiter.api.Assertions.fail;
2322
import static org.junit.jupiter.api.condition.OS.WINDOWS;
2423

@@ -28,6 +27,7 @@
2827
import java.util.concurrent.atomic.AtomicBoolean;
2928
import java.util.concurrent.atomic.AtomicReference;
3029

30+
import org.jspecify.annotations.Nullable;
3131
import org.junit.jupiter.api.function.Executable;
3232
import org.junit.platform.commons.util.ExceptionUtils;
3333
import org.opentest4j.AssertionFailedError;
@@ -81,7 +81,7 @@ void assertTimeoutPreemptivelyForExecutableThatCompletesAfterTheTimeout() {
8181
() -> assertTimeoutPreemptively(PREEMPTIVE_TIMEOUT, this::waitForInterrupt));
8282
assertMessageEquals(error, "execution timed out after " + PREEMPTIVE_TIMEOUT.toMillis() + " ms");
8383
assertMessageStartsWith(error.getCause(), "Execution timed out in ");
84-
assertStackTraceContains(error.getCause().getStackTrace(), "CountDownLatch", "await");
84+
assertStackTraceContains(error.getCause(), "CountDownLatch", "await");
8585
}
8686

8787
@Test
@@ -91,7 +91,7 @@ void assertTimeoutPreemptivelyWithMessageForExecutableThatCompletesAfterTheTimeo
9191
assertMessageEquals(error,
9292
"Tempus Fugit ==> execution timed out after " + PREEMPTIVE_TIMEOUT.toMillis() + " ms");
9393
assertMessageStartsWith(error.getCause(), "Execution timed out in ");
94-
assertStackTraceContains(error.getCause().getStackTrace(), "CountDownLatch", "await");
94+
assertStackTraceContains(error.getCause(), "CountDownLatch", "await");
9595
}
9696

9797
@Test
@@ -102,7 +102,7 @@ void assertTimeoutPreemptivelyWithMessageSupplierForExecutableThatCompletesAfter
102102
assertMessageEquals(error,
103103
"Tempus Fugit ==> execution timed out after " + PREEMPTIVE_TIMEOUT.toMillis() + " ms");
104104
assertMessageStartsWith(error.getCause(), "Execution timed out in ");
105-
assertStackTraceContains(error.getCause().getStackTrace(), "CountDownLatch", "await");
105+
assertStackTraceContains(error.getCause(), "CountDownLatch", "await");
106106
}
107107

108108
@Test
@@ -156,7 +156,7 @@ void assertTimeoutPreemptivelyForSupplierThatCompletesAfterTheTimeout() {
156156

157157
assertMessageEquals(error, "execution timed out after " + PREEMPTIVE_TIMEOUT.toMillis() + " ms");
158158
assertMessageStartsWith(error.getCause(), "Execution timed out in ");
159-
assertStackTraceContains(error.getCause().getStackTrace(), "CountDownLatch", "await");
159+
assertStackTraceContains(error.getCause(), "CountDownLatch", "await");
160160
}
161161

162162
@Test
@@ -171,7 +171,7 @@ void assertTimeoutPreemptivelyWithMessageForSupplierThatCompletesAfterTheTimeout
171171
assertMessageEquals(error,
172172
"Tempus Fugit ==> execution timed out after " + PREEMPTIVE_TIMEOUT.toMillis() + " ms");
173173
assertMessageStartsWith(error.getCause(), "Execution timed out in ");
174-
assertStackTraceContains(error.getCause().getStackTrace(), "CountDownLatch", "await");
174+
assertStackTraceContains(error.getCause(), "CountDownLatch", "await");
175175
}
176176

177177
@Test
@@ -186,15 +186,16 @@ void assertTimeoutPreemptivelyWithMessageSupplierForSupplierThatCompletesAfterTh
186186
assertMessageEquals(error,
187187
"Tempus Fugit ==> execution timed out after " + PREEMPTIVE_TIMEOUT.toMillis() + " ms");
188188
assertMessageStartsWith(error.getCause(), "Execution timed out in ");
189-
assertStackTraceContains(error.getCause().getStackTrace(), "CountDownLatch", "await");
189+
assertStackTraceContains(error.getCause(), "CountDownLatch", "await");
190190
}
191191

192192
@Test
193193
void assertTimeoutPreemptivelyUsesThreadsWithSpecificNamePrefix() {
194194
AtomicReference<String> threadName = new AtomicReference<>("");
195195
assertTimeoutPreemptively(ofMillis(1000), () -> threadName.set(Thread.currentThread().getName()));
196-
assertTrue(threadName.get().startsWith("junit-timeout-thread-"),
197-
"Thread name does not match the expected prefix");
196+
assertThat(threadName.get()) //
197+
.withFailMessage("Thread name does not match the expected prefix") //
198+
.startsWith("junit-timeout-thread-");
198199
}
199200

200201
@Test
@@ -244,8 +245,9 @@ private void waitForInterrupt() {
244245
/**
245246
* Assert the given stack trace elements contain an element with the given class name and method name.
246247
*/
247-
private static void assertStackTraceContains(StackTraceElement[] stackTrace, String className, String methodName) {
248-
assertThat(stackTrace).anySatisfy(element -> {
248+
private static void assertStackTraceContains(@Nullable Throwable throwable, String className, String methodName) {
249+
assertThat(throwable).isNotNull();
250+
assertThat(throwable.getStackTrace()).anySatisfy(element -> {
249251
assertThat(element.getClassName()).endsWith(className);
250252
assertThat(element.getMethodName()).isEqualTo(methodName);
251253
});

jupiter-tests/src/test/java/org/junit/jupiter/api/AssertionTestUtils.java

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
import java.io.Serializable;
1414
import java.util.Objects;
1515

16+
import org.apache.groovy.parser.antlr4.util.StringUtils;
17+
import org.jspecify.annotations.Nullable;
1618
import org.opentest4j.AssertionFailedError;
1719
import org.opentest4j.ValueWrapper;
1820

@@ -27,7 +29,7 @@ static void expectAssertionFailedError() {
2729
}
2830

2931
static void assertEmptyMessage(Throwable ex) throws AssertionError {
30-
if (!ex.getMessage().isEmpty()) {
32+
if (!StringUtils.isEmpty(ex.getMessage())) {
3133
throw new AssertionError("Exception message should be empty, but was [" + ex.getMessage() + "].");
3234
}
3335
}
@@ -39,35 +41,41 @@ static void assertMessageEquals(Throwable ex, String msg) throws AssertionError
3941
}
4042

4143
static void assertMessageMatches(Throwable ex, String regex) throws AssertionError {
42-
if (!ex.getMessage().matches(regex)) {
44+
if (ex.getMessage() == null || !ex.getMessage().matches(regex)) {
4345
throw new AssertionError("Exception message should match regular expression [" + regex + "], but was ["
4446
+ ex.getMessage() + "].");
4547
}
4648
}
4749

48-
static void assertMessageStartsWith(Throwable ex, String msg) throws AssertionError {
49-
if (!ex.getMessage().startsWith(msg)) {
50+
static void assertMessageStartsWith(@Nullable Throwable ex, String msg) throws AssertionError {
51+
if (ex == null) {
52+
throw new AssertionError("Cause should not have been null");
53+
}
54+
if (ex.getMessage() == null || !ex.getMessage().startsWith(msg)) {
5055
throw new AssertionError(
5156
"Exception message should start with [" + msg + "], but was [" + ex.getMessage() + "].");
5257
}
5358
}
5459

5560
static void assertMessageEndsWith(Throwable ex, String msg) throws AssertionError {
56-
if (!ex.getMessage().endsWith(msg)) {
61+
if (ex.getMessage() == null || !ex.getMessage().endsWith(msg)) {
5762
throw new AssertionError(
5863
"Exception message should end with [" + msg + "], but was [" + ex.getMessage() + "].");
5964
}
6065
}
6166

62-
static void assertMessageContains(Throwable ex, String msg) throws AssertionError {
63-
if (!ex.getMessage().contains(msg)) {
67+
static void assertMessageContains(@Nullable Throwable ex, String msg) throws AssertionError {
68+
if (ex == null) {
69+
throw new AssertionError("Cause should not have been null");
70+
}
71+
if (ex.getMessage() == null || !ex.getMessage().contains(msg)) {
6472
throw new AssertionError(
6573
"Exception message should contain [" + msg + "], but was [" + ex.getMessage() + "].");
6674
}
6775
}
6876

69-
static void assertExpectedAndActualValues(AssertionFailedError ex, Object expected, Object actual)
70-
throws AssertionError {
77+
static void assertExpectedAndActualValues(AssertionFailedError ex, @Nullable Object expected,
78+
@Nullable Object actual) throws AssertionError {
7179
if (!wrapsEqualValue(ex.getExpected(), expected)) {
7280
throw new AssertionError("Expected value in AssertionFailedError should equal ["
7381
+ ValueWrapper.create(expected) + "], but was [" + ex.getExpected() + "].");
@@ -78,7 +86,7 @@ static void assertExpectedAndActualValues(AssertionFailedError ex, Object expect
7886
}
7987
}
8088

81-
static boolean wrapsEqualValue(ValueWrapper wrapper, Object value) {
89+
static boolean wrapsEqualValue(ValueWrapper wrapper, @Nullable Object value) {
8290
if (value == null || value instanceof Serializable) {
8391
return Objects.equals(value, wrapper.getValue());
8492
}

0 commit comments

Comments
 (0)