Skip to content

Commit 04ced4e

Browse files
committed
tests: Make JUnit lifecycle tests more precise
We also track the instance on which a given method is invoked and verify that the `ExtensionContext` contains consistent information. This prepares for future changes to `Lifecycle.PER_EXECUTION`.
1 parent 0c2aa0b commit 04ced4e

File tree

3 files changed

+177
-96
lines changed

3 files changed

+177
-96
lines changed

examples/junit/src/test/java/com/example/BUILD.bazel

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ java_binary(
2121
"//deploy:jazzer-junit",
2222
"//examples/junit/src/main/java/com/example:parser",
2323
"//examples/junit/src/test/resources:example_seed_corpora",
24+
"@maven//:com_google_truth_extensions_truth_java8_extension",
2425
"@maven//:com_google_truth_truth",
2526
"@maven//:org_junit_jupiter_junit_jupiter_api",
2627
"@maven//:org_junit_jupiter_junit_jupiter_params",
@@ -84,6 +85,7 @@ java_fuzz_target_test(
8485
":test_successful_exception",
8586
"//examples/junit/src/main/java/com/example:parser",
8687
"//src/main/java/com/code_intelligence/jazzer/junit:fuzz_test",
88+
"@maven//:com_google_truth_extensions_truth_java8_extension",
8789
"@maven//:com_google_truth_truth",
8890
"@maven//:org_junit_jupiter_junit_jupiter_api",
8991
],
@@ -105,6 +107,7 @@ java_fuzz_target_test(
105107
":test_successful_exception",
106108
"//examples/junit/src/main/java/com/example:parser",
107109
"//src/main/java/com/code_intelligence/jazzer/junit:fuzz_test",
110+
"@maven//:com_google_truth_extensions_truth_java8_extension",
108111
"@maven//:com_google_truth_truth",
109112
"@maven//:org_junit_jupiter_junit_jupiter_api",
110113
],

examples/junit/src/test/java/com/example/PerExecutionLifecycleFuzzTest.java

Lines changed: 87 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,19 @@
1717
package com.example;
1818

1919
import static com.google.common.truth.Truth.assertThat;
20-
import static java.util.Arrays.asList;
21-
import static java.util.Collections.unmodifiableList;
20+
import static com.google.common.truth.Truth8.assertThat;
21+
import static java.util.stream.Collectors.collectingAndThen;
22+
import static java.util.stream.Collectors.toList;
2223

2324
import com.code_intelligence.jazzer.junit.FuzzTest;
2425
import com.code_intelligence.jazzer.junit.Lifecycle;
2526
import com.example.PerExecutionLifecycleFuzzTest.LifecycleCallbacks1;
2627
import com.example.PerExecutionLifecycleFuzzTest.LifecycleCallbacks2;
2728
import com.example.PerExecutionLifecycleFuzzTest.LifecycleCallbacks3;
2829
import java.util.ArrayList;
30+
import java.util.Collections;
2931
import java.util.List;
32+
import java.util.stream.Stream;
3033
import org.junit.jupiter.api.AfterAll;
3134
import org.junit.jupiter.api.AfterEach;
3235
import org.junit.jupiter.api.BeforeAll;
@@ -48,58 +51,83 @@
4851
class PerExecutionLifecycleFuzzTest {
4952
private static final ArrayList<String> events = new ArrayList<>();
5053
private static final long RUNS = 3;
54+
private static int nextInstanceId = 1;
5155

52-
private boolean beforeEachCalledOnInstance = false;
53-
private boolean testInstancePostProcessorCalledOnInstance = false;
56+
private final int instanceId = nextInstanceId++;
5457

5558
@BeforeAll
5659
static void beforeAll() {
5760
events.add("beforeAll");
5861
}
5962

63+
private void addEvent(String what) {
64+
events.add(what + " on " + instanceId);
65+
}
66+
6067
@BeforeEach
6168
void beforeEach1() {
62-
events.add("beforeEach1");
63-
beforeEachCalledOnInstance = true;
69+
addEvent("beforeEach1");
6470
}
6571

6672
@BeforeEach
6773
void beforeEach2() {
68-
events.add("beforeEach2");
74+
addEvent("beforeEach2");
6975
}
7076

7177
@BeforeEach
7278
void beforeEach3() {
73-
events.add("beforeEach3");
79+
addEvent("beforeEach3");
7480
}
7581

7682
@Disabled
7783
@FuzzTest
7884
void disabledFuzz(byte[] data) {
79-
events.add("disabledFuzz");
85+
addEvent("disabledFuzz");
8086
throw new AssertionError("This test should not be executed");
8187
}
8288

8389
@FuzzTest(maxExecutions = RUNS, lifecycle = Lifecycle.PER_EXECUTION)
8490
void lifecycleFuzz(byte[] data) {
85-
events.add("lifecycleFuzz");
86-
assertThat(beforeEachCalledOnInstance).isTrue();
87-
assertThat(testInstancePostProcessorCalledOnInstance).isTrue();
91+
addEvent("lifecycleFuzz");
8892
}
8993

9094
@AfterEach
9195
void afterEach1() {
92-
events.add("afterEach1");
96+
addEvent("afterEach1");
9397
}
9498

9599
@AfterEach
96100
void afterEach2() {
97-
events.add("afterEach2");
101+
addEvent("afterEach2");
98102
}
99103

100104
@AfterEach
101105
void afterEach3() {
102-
events.add("afterEach3");
106+
addEvent("afterEach3");
107+
}
108+
109+
static List<String> expectedBeforeEachEvents(int instanceId) {
110+
return Stream.of(
111+
"beforeEachCallback1",
112+
"beforeEachCallback2",
113+
"beforeEachCallback3",
114+
"beforeEach1",
115+
"beforeEach2",
116+
"beforeEach3")
117+
.map(s -> s + " on " + instanceId)
118+
.collect(collectingAndThen(toList(), Collections::unmodifiableList));
119+
}
120+
121+
static List<String> expectedAfterEachEvents(int instanceId) {
122+
return Stream.of(
123+
"afterEach1",
124+
"afterEach2",
125+
"afterEach3",
126+
"afterEachCallback3",
127+
"afterEachCallback2",
128+
"afterEachCallback1")
129+
.map(s -> s + " on " + instanceId)
130+
.collect(collectingAndThen(toList(), Collections::unmodifiableList));
103131
}
104132

105133
@AfterAll
@@ -110,39 +138,27 @@ static void afterAll() throws TestSuccessfulException {
110138
boolean isFuzzingFromCommandLine = System.getenv("JAZZER_FUZZ") == null;
111139
boolean isFuzzingFromJUnit = !isFuzzingFromCommandLine && !isRegressionTest;
112140

113-
final List<String> expectedBeforeEachEvents =
114-
unmodifiableList(
115-
asList(
116-
"beforeEachCallback1",
117-
"beforeEachCallback2",
118-
"beforeEachCallback3",
119-
"beforeEach1",
120-
"beforeEach2",
121-
"beforeEach3"));
122-
final List<String> expectedAfterEachEvents =
123-
unmodifiableList(
124-
asList(
125-
"afterEach1",
126-
"afterEach2",
127-
"afterEach3",
128-
"afterEachCallback3",
129-
"afterEachCallback2",
130-
"afterEachCallback1"));
131-
132141
ArrayList<String> expectedEvents = new ArrayList<>();
133142
expectedEvents.add("beforeAll");
134143

144+
int firstFuzzingInstanceId = 1;
135145
// When run from the command-line, the fuzz test is not separately executed on the empty seed.
136146
if (isRegressionTest || isFuzzingFromJUnit) {
137-
expectedEvents.addAll(expectedBeforeEachEvents);
138-
expectedEvents.add("lifecycleFuzz");
139-
expectedEvents.addAll(expectedAfterEachEvents);
147+
expectedEvents.add("postProcessTestInstance on 1");
148+
expectedEvents.addAll(expectedBeforeEachEvents(1));
149+
expectedEvents.add("lifecycleFuzz on 1");
150+
expectedEvents.addAll(expectedAfterEachEvents(1));
151+
firstFuzzingInstanceId++;
140152
}
141153
if (isFuzzingFromJUnit || isFuzzingFromCommandLine) {
142-
for (int i = 0; i < RUNS; i++) {
143-
expectedEvents.addAll(expectedBeforeEachEvents);
144-
expectedEvents.add("lifecycleFuzz");
145-
expectedEvents.addAll(expectedAfterEachEvents);
154+
expectedEvents.add("postProcessTestInstance on " + firstFuzzingInstanceId);
155+
for (int i = 1; i <= RUNS; i++) {
156+
// TODO: Every execution should use its own instance, i.e., this should be
157+
// firstFuzzingInstanceId + i.
158+
int expectedId = firstFuzzingInstanceId;
159+
expectedEvents.addAll(expectedBeforeEachEvents(expectedId));
160+
expectedEvents.add("lifecycleFuzz on " + expectedId);
161+
expectedEvents.addAll(expectedAfterEachEvents(expectedId));
146162
}
147163
}
148164

@@ -152,46 +168,69 @@ static void afterAll() throws TestSuccessfulException {
152168
throw new TestSuccessfulException("Lifecycle methods invoked as expected");
153169
}
154170

171+
static void assertConsistentTestInstances(ExtensionContext extensionContext) {
172+
assertThat(extensionContext.getTestInstance().get())
173+
.isSameInstanceAs(extensionContext.getRequiredTestInstance());
174+
assertThat(extensionContext.getTestInstances().get())
175+
.isSameInstanceAs(extensionContext.getRequiredTestInstances());
176+
assertThat(extensionContext.getRequiredTestInstances().getAllInstances())
177+
.containsExactly(extensionContext.getRequiredTestInstance());
178+
}
179+
155180
static class LifecycleInstancePostProcessor implements TestInstancePostProcessor {
156181
@Override
157182
public void postProcessTestInstance(Object o, ExtensionContext extensionContext) {
158-
((PerExecutionLifecycleFuzzTest) o).testInstancePostProcessorCalledOnInstance = true;
183+
assertThat(extensionContext.getTestInstance()).isEmpty();
184+
assertThat(extensionContext.getTestInstances()).isEmpty();
185+
((PerExecutionLifecycleFuzzTest) o).addEvent("postProcessTestInstance");
159186
}
160187
}
161188

162189
static class LifecycleCallbacks1 implements BeforeEachCallback, AfterEachCallback {
163190
@Override
164191
public void beforeEach(ExtensionContext extensionContext) {
165-
events.add("beforeEachCallback1");
192+
assertConsistentTestInstances(extensionContext);
193+
((PerExecutionLifecycleFuzzTest) extensionContext.getRequiredTestInstance())
194+
.addEvent("beforeEachCallback1");
166195
}
167196

168197
@Override
169198
public void afterEach(ExtensionContext extensionContext) {
170-
events.add("afterEachCallback1");
199+
assertConsistentTestInstances(extensionContext);
200+
((PerExecutionLifecycleFuzzTest) extensionContext.getRequiredTestInstance())
201+
.addEvent("afterEachCallback1");
171202
}
172203
}
173204

174205
static class LifecycleCallbacks2 implements BeforeEachCallback, AfterEachCallback {
175206
@Override
176207
public void beforeEach(ExtensionContext extensionContext) {
177-
events.add("beforeEachCallback2");
208+
assertConsistentTestInstances(extensionContext);
209+
((PerExecutionLifecycleFuzzTest) extensionContext.getRequiredTestInstance())
210+
.addEvent("beforeEachCallback2");
178211
}
179212

180213
@Override
181214
public void afterEach(ExtensionContext extensionContext) {
182-
events.add("afterEachCallback2");
215+
assertConsistentTestInstances(extensionContext);
216+
((PerExecutionLifecycleFuzzTest) extensionContext.getRequiredTestInstance())
217+
.addEvent("afterEachCallback2");
183218
}
184219
}
185220

186221
static class LifecycleCallbacks3 implements BeforeEachCallback, AfterEachCallback {
187222
@Override
188223
public void beforeEach(ExtensionContext extensionContext) {
189-
events.add("beforeEachCallback3");
224+
assertConsistentTestInstances(extensionContext);
225+
((PerExecutionLifecycleFuzzTest) extensionContext.getRequiredTestInstance())
226+
.addEvent("beforeEachCallback3");
190227
}
191228

192229
@Override
193230
public void afterEach(ExtensionContext extensionContext) {
194-
events.add("afterEachCallback3");
231+
assertConsistentTestInstances(extensionContext);
232+
((PerExecutionLifecycleFuzzTest) extensionContext.getRequiredTestInstance())
233+
.addEvent("afterEachCallback3");
195234
}
196235
}
197236
}

0 commit comments

Comments
 (0)