diff --git a/examples/junit/src/test/java/com/example/BUILD.bazel b/examples/junit/src/test/java/com/example/BUILD.bazel index e3b9465ed..37c577916 100644 --- a/examples/junit/src/test/java/com/example/BUILD.bazel +++ b/examples/junit/src/test/java/com/example/BUILD.bazel @@ -84,6 +84,7 @@ java_fuzz_target_test( ":junit_runtime", ], deps = [ + ":lifecycle_recording_test_base", ":test_successful_exception", "//examples/junit/src/main/java/com/example:parser", "//src/main/java/com/code_intelligence/jazzer/junit:fuzz_test", @@ -107,6 +108,7 @@ java_fuzz_target_test( ":junit_runtime", ], deps = [ + ":lifecycle_recording_test_base", ":test_successful_exception", "//examples/junit/src/main/java/com/example:parser", "//src/main/java/com/code_intelligence/jazzer/junit:fuzz_test", @@ -131,6 +133,7 @@ java_fuzz_target_test( ":junit_runtime", ], deps = [ + ":lifecycle_recording_test_base", ":test_successful_exception", "//examples/junit/src/main/java/com/example:parser", "//src/main/java/com/code_intelligence/jazzer/junit:fuzz_test", @@ -309,6 +312,18 @@ java_fuzz_target_test( ] ] +java_library( + name = "lifecycle_recording_test_base", + testonly = True, + srcs = ["LifecycleRecordingTestBase.java"], + deps = [ + "//src/main/java/com/code_intelligence/jazzer/junit:fuzz_test", + "@maven//:com_google_truth_extensions_truth_java8_extension", + "@maven//:com_google_truth_truth", + "@maven//:org_junit_jupiter_junit_jupiter_api", + ], +) + java_library( name = "junit_runtime", runtime_deps = [ diff --git a/examples/junit/src/test/java/com/example/LifecycleRecordingTestBase.java b/examples/junit/src/test/java/com/example/LifecycleRecordingTestBase.java new file mode 100644 index 000000000..19641b7e8 --- /dev/null +++ b/examples/junit/src/test/java/com/example/LifecycleRecordingTestBase.java @@ -0,0 +1,191 @@ +/* + * Copyright 2023 Code Intelligence GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example; + +import static com.google.common.truth.Truth.assertThat; +import static com.google.common.truth.Truth8.assertThat; +import static java.util.stream.Collectors.collectingAndThen; +import static java.util.stream.Collectors.toList; + +import com.code_intelligence.jazzer.junit.FuzzTest; +import com.example.LifecycleRecordingTestBase.LifecycleCallbacks1; +import com.example.LifecycleRecordingTestBase.LifecycleCallbacks2; +import com.example.LifecycleRecordingTestBase.LifecycleCallbacks3; +import java.util.Collections; +import java.util.List; +import java.util.stream.Stream; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.TestMethodOrder; +import org.junit.jupiter.api.extension.AfterEachCallback; +import org.junit.jupiter.api.extension.BeforeEachCallback; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.TestInstancePostProcessor; + +@TestMethodOrder(MethodOrderer.MethodName.class) +@ExtendWith(LifecycleRecordingTestBase.LifecycleInstancePostProcessor.class) +@ExtendWith(LifecycleCallbacks1.class) +@ExtendWith(LifecycleCallbacks2.class) +@ExtendWith(LifecycleCallbacks3.class) +public abstract class LifecycleRecordingTestBase { + + protected static final long RUNS = 3; + protected static final boolean IS_REGRESSION_TEST = "".equals(System.getenv("JAZZER_FUZZ")); + protected static final boolean IS_FUZZING_FROM_COMMAND_LINE = + System.getenv("JAZZER_FUZZ") == null; + protected static final boolean IS_FUZZING_FROM_JUNIT = + !IS_FUZZING_FROM_COMMAND_LINE && !IS_REGRESSION_TEST; + + private static int nextInstanceId = 1; + private final int instanceId = nextInstanceId++; + + protected abstract List events(); + + static List expectedBeforeEachEvents(int instanceId) { + return Stream.of( + "beforeEachCallback1", + "beforeEachCallback2", + "beforeEachCallback3", + "beforeEach1", + "beforeEach2", + "beforeEach3") + .map(s -> s + " on " + instanceId) + .collect(collectingAndThen(toList(), Collections::unmodifiableList)); + } + + static List expectedAfterEachEvents(int instanceId) { + return Stream.of( + "afterEach1", + "afterEach2", + "afterEach3", + "afterEachCallback3", + "afterEachCallback2", + "afterEachCallback1") + .map(s -> s + " on " + instanceId) + .collect(collectingAndThen(toList(), Collections::unmodifiableList)); + } + + static void assertConsistentTestInstances(ExtensionContext extensionContext) { + assertThat(extensionContext.getTestInstance().get()) + .isSameInstanceAs(extensionContext.getRequiredTestInstance()); + assertThat(extensionContext.getTestInstances().get()) + .isSameInstanceAs(extensionContext.getRequiredTestInstances()); + assertThat(extensionContext.getRequiredTestInstances().getAllInstances()) + .containsExactly(extensionContext.getRequiredTestInstance()); + } + + protected void addEvent(String what) { + events().add(what + " on " + instanceId); + } + + @Disabled + @FuzzTest + void disabledFuzz(byte[] data) { + addEvent("disabledFuzz"); + throw new AssertionError("This test should not be executed"); + } + + @BeforeEach + void beforeEach1() { + addEvent("beforeEach1"); + } + + @BeforeEach + void beforeEach2() { + addEvent("beforeEach2"); + } + + @BeforeEach + void beforeEach3() { + addEvent("beforeEach3"); + } + + @AfterEach + void afterEach1() { + addEvent("afterEach1"); + } + + @AfterEach + void afterEach2() { + addEvent("afterEach2"); + } + + @AfterEach + void afterEach3() { + addEvent("afterEach3"); + } + + static class LifecycleInstancePostProcessor implements TestInstancePostProcessor { + @Override + public void postProcessTestInstance(Object o, ExtensionContext extensionContext) { + assertThat(extensionContext.getTestInstance()).isEmpty(); + assertThat(extensionContext.getTestInstances()).isEmpty(); + ((LifecycleRecordingTestBase) o).addEvent("postProcessTestInstance"); + } + } + + static class LifecycleCallbacks1 implements BeforeEachCallback, AfterEachCallback { + @Override + public void beforeEach(ExtensionContext extensionContext) { + assertConsistentTestInstances(extensionContext); + ((LifecycleRecordingTestBase) extensionContext.getRequiredTestInstance()) + .addEvent("beforeEachCallback1"); + } + + @Override + public void afterEach(ExtensionContext extensionContext) { + assertConsistentTestInstances(extensionContext); + ((LifecycleRecordingTestBase) extensionContext.getRequiredTestInstance()) + .addEvent("afterEachCallback1"); + } + } + + static class LifecycleCallbacks2 implements BeforeEachCallback, AfterEachCallback { + @Override + public void beforeEach(ExtensionContext extensionContext) { + assertConsistentTestInstances(extensionContext); + ((LifecycleRecordingTestBase) extensionContext.getRequiredTestInstance()) + .addEvent("beforeEachCallback2"); + } + + @Override + public void afterEach(ExtensionContext extensionContext) { + assertConsistentTestInstances(extensionContext); + ((LifecycleRecordingTestBase) extensionContext.getRequiredTestInstance()) + .addEvent("afterEachCallback2"); + } + } + + static class LifecycleCallbacks3 implements BeforeEachCallback, AfterEachCallback { + @Override + public void beforeEach(ExtensionContext extensionContext) { + assertConsistentTestInstances(extensionContext); + ((LifecycleRecordingTestBase) extensionContext.getRequiredTestInstance()) + .addEvent("beforeEachCallback3"); + } + + @Override + public void afterEach(ExtensionContext extensionContext) { + assertConsistentTestInstances(extensionContext); + ((LifecycleRecordingTestBase) extensionContext.getRequiredTestInstance()) + .addEvent("afterEachCallback3"); + } + } +} diff --git a/examples/junit/src/test/java/com/example/PerExecutionLifecycleFuzzTest.java b/examples/junit/src/test/java/com/example/PerExecutionLifecycleFuzzTest.java index 8d61f7d31..642452a1c 100644 --- a/examples/junit/src/test/java/com/example/PerExecutionLifecycleFuzzTest.java +++ b/examples/junit/src/test/java/com/example/PerExecutionLifecycleFuzzTest.java @@ -17,140 +17,44 @@ package com.example; import static com.google.common.truth.Truth.assertThat; -import static com.google.common.truth.Truth8.assertThat; -import static java.util.stream.Collectors.collectingAndThen; -import static java.util.stream.Collectors.toList; import com.code_intelligence.jazzer.junit.FuzzTest; import com.code_intelligence.jazzer.junit.Lifecycle; -import com.example.PerExecutionLifecycleFuzzTest.LifecycleCallbacks1; -import com.example.PerExecutionLifecycleFuzzTest.LifecycleCallbacks2; -import com.example.PerExecutionLifecycleFuzzTest.LifecycleCallbacks3; import java.util.ArrayList; -import java.util.Collections; import java.util.List; -import java.util.stream.Stream; import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.MethodOrderer; -import org.junit.jupiter.api.TestMethodOrder; -import org.junit.jupiter.api.extension.AfterEachCallback; -import org.junit.jupiter.api.extension.BeforeEachCallback; -import org.junit.jupiter.api.extension.ExtendWith; -import org.junit.jupiter.api.extension.ExtensionContext; -import org.junit.jupiter.api.extension.TestInstancePostProcessor; -@TestMethodOrder(MethodOrderer.MethodName.class) -@ExtendWith(PerExecutionLifecycleFuzzTest.LifecycleInstancePostProcessor.class) -@ExtendWith(LifecycleCallbacks1.class) -@ExtendWith(LifecycleCallbacks2.class) -@ExtendWith(LifecycleCallbacks3.class) -class PerExecutionLifecycleFuzzTest { +class PerExecutionLifecycleFuzzTest extends LifecycleRecordingTestBase { private static final ArrayList events = new ArrayList<>(); - private static final long RUNS = 3; - private static int nextInstanceId = 1; - - private final int instanceId = nextInstanceId++; @BeforeAll static void beforeAll() { events.add("beforeAll"); } - private void addEvent(String what) { - events.add(what + " on " + instanceId); - } - - @BeforeEach - void beforeEach1() { - addEvent("beforeEach1"); - } - - @BeforeEach - void beforeEach2() { - addEvent("beforeEach2"); - } - - @BeforeEach - void beforeEach3() { - addEvent("beforeEach3"); - } - - @Disabled - @FuzzTest - void disabledFuzz(byte[] data) { - addEvent("disabledFuzz"); - throw new AssertionError("This test should not be executed"); - } - @FuzzTest(maxExecutions = RUNS, lifecycle = Lifecycle.PER_EXECUTION) void lifecycleFuzz(byte[] data) { addEvent("lifecycleFuzz"); } - @AfterEach - void afterEach1() { - addEvent("afterEach1"); - } - - @AfterEach - void afterEach2() { - addEvent("afterEach2"); - } - - @AfterEach - void afterEach3() { - addEvent("afterEach3"); - } - - static List expectedBeforeEachEvents(int instanceId) { - return Stream.of( - "beforeEachCallback1", - "beforeEachCallback2", - "beforeEachCallback3", - "beforeEach1", - "beforeEach2", - "beforeEach3") - .map(s -> s + " on " + instanceId) - .collect(collectingAndThen(toList(), Collections::unmodifiableList)); - } - - static List expectedAfterEachEvents(int instanceId) { - return Stream.of( - "afterEach1", - "afterEach2", - "afterEach3", - "afterEachCallback3", - "afterEachCallback2", - "afterEachCallback1") - .map(s -> s + " on " + instanceId) - .collect(collectingAndThen(toList(), Collections::unmodifiableList)); - } - @AfterAll static void afterAll() throws TestSuccessfulException { events.add("afterAll"); - boolean isRegressionTest = "".equals(System.getenv("JAZZER_FUZZ")); - boolean isFuzzingFromCommandLine = System.getenv("JAZZER_FUZZ") == null; - boolean isFuzzingFromJUnit = !isFuzzingFromCommandLine && !isRegressionTest; - ArrayList expectedEvents = new ArrayList<>(); expectedEvents.add("beforeAll"); int firstFuzzingInstanceId = 1; // When run from the command-line, the fuzz test is not separately executed on the empty seed. - if (isRegressionTest || isFuzzingFromJUnit) { + if (IS_REGRESSION_TEST || IS_FUZZING_FROM_JUNIT) { expectedEvents.add("postProcessTestInstance on 1"); expectedEvents.addAll(expectedBeforeEachEvents(1)); expectedEvents.add("lifecycleFuzz on 1"); expectedEvents.addAll(expectedAfterEachEvents(1)); firstFuzzingInstanceId++; } - if (isFuzzingFromJUnit || isFuzzingFromCommandLine) { + if (IS_FUZZING_FROM_JUNIT || IS_FUZZING_FROM_COMMAND_LINE) { // See the comment in JUnitLifecycleMethodsInvoker#beforeFirstExecution() for an explanation // of why we see the lifecycle events on firstFuzzingInstanceId. expectedEvents.add("postProcessTestInstance on " + firstFuzzingInstanceId); @@ -171,69 +75,8 @@ static void afterAll() throws TestSuccessfulException { throw new TestSuccessfulException("Lifecycle methods invoked as expected"); } - static void assertConsistentTestInstances(ExtensionContext extensionContext) { - assertThat(extensionContext.getTestInstance().get()) - .isSameInstanceAs(extensionContext.getRequiredTestInstance()); - assertThat(extensionContext.getTestInstances().get()) - .isSameInstanceAs(extensionContext.getRequiredTestInstances()); - assertThat(extensionContext.getRequiredTestInstances().getAllInstances()) - .containsExactly(extensionContext.getRequiredTestInstance()); - } - - static class LifecycleInstancePostProcessor implements TestInstancePostProcessor { - @Override - public void postProcessTestInstance(Object o, ExtensionContext extensionContext) { - assertThat(extensionContext.getTestInstance()).isEmpty(); - assertThat(extensionContext.getTestInstances()).isEmpty(); - ((PerExecutionLifecycleFuzzTest) o).addEvent("postProcessTestInstance"); - } - } - - static class LifecycleCallbacks1 implements BeforeEachCallback, AfterEachCallback { - @Override - public void beforeEach(ExtensionContext extensionContext) { - assertConsistentTestInstances(extensionContext); - ((PerExecutionLifecycleFuzzTest) extensionContext.getRequiredTestInstance()) - .addEvent("beforeEachCallback1"); - } - - @Override - public void afterEach(ExtensionContext extensionContext) { - assertConsistentTestInstances(extensionContext); - ((PerExecutionLifecycleFuzzTest) extensionContext.getRequiredTestInstance()) - .addEvent("afterEachCallback1"); - } - } - - static class LifecycleCallbacks2 implements BeforeEachCallback, AfterEachCallback { - @Override - public void beforeEach(ExtensionContext extensionContext) { - assertConsistentTestInstances(extensionContext); - ((PerExecutionLifecycleFuzzTest) extensionContext.getRequiredTestInstance()) - .addEvent("beforeEachCallback2"); - } - - @Override - public void afterEach(ExtensionContext extensionContext) { - assertConsistentTestInstances(extensionContext); - ((PerExecutionLifecycleFuzzTest) extensionContext.getRequiredTestInstance()) - .addEvent("afterEachCallback2"); - } - } - - static class LifecycleCallbacks3 implements BeforeEachCallback, AfterEachCallback { - @Override - public void beforeEach(ExtensionContext extensionContext) { - assertConsistentTestInstances(extensionContext); - ((PerExecutionLifecycleFuzzTest) extensionContext.getRequiredTestInstance()) - .addEvent("beforeEachCallback3"); - } - - @Override - public void afterEach(ExtensionContext extensionContext) { - assertConsistentTestInstances(extensionContext); - ((PerExecutionLifecycleFuzzTest) extensionContext.getRequiredTestInstance()) - .addEvent("afterEachCallback3"); - } + @Override + protected List events() { + return events; } } diff --git a/examples/junit/src/test/java/com/example/PerExecutionLifecycleWithFindingFuzzTest.java b/examples/junit/src/test/java/com/example/PerExecutionLifecycleWithFindingFuzzTest.java index fef745a73..b2b3979aa 100644 --- a/examples/junit/src/test/java/com/example/PerExecutionLifecycleWithFindingFuzzTest.java +++ b/examples/junit/src/test/java/com/example/PerExecutionLifecycleWithFindingFuzzTest.java @@ -17,75 +17,23 @@ package com.example; import static com.google.common.truth.Truth.assertThat; -import static com.google.common.truth.Truth8.assertThat; -import static java.util.stream.Collectors.collectingAndThen; -import static java.util.stream.Collectors.toList; import com.code_intelligence.jazzer.junit.FuzzTest; import com.code_intelligence.jazzer.junit.Lifecycle; -import com.example.PerExecutionLifecycleWithFindingFuzzTest.LifecycleCallbacks1; -import com.example.PerExecutionLifecycleWithFindingFuzzTest.LifecycleCallbacks2; -import com.example.PerExecutionLifecycleWithFindingFuzzTest.LifecycleCallbacks3; import java.io.IOException; import java.util.ArrayList; -import java.util.Collections; import java.util.List; -import java.util.stream.Stream; import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.MethodOrderer; -import org.junit.jupiter.api.TestMethodOrder; -import org.junit.jupiter.api.extension.AfterEachCallback; -import org.junit.jupiter.api.extension.BeforeEachCallback; -import org.junit.jupiter.api.extension.ExtendWith; -import org.junit.jupiter.api.extension.ExtensionContext; -import org.junit.jupiter.api.extension.TestInstancePostProcessor; -@TestMethodOrder(MethodOrderer.MethodName.class) -@ExtendWith(PerExecutionLifecycleWithFindingFuzzTest.LifecycleInstancePostProcessor.class) -@ExtendWith(LifecycleCallbacks1.class) -@ExtendWith(LifecycleCallbacks2.class) -@ExtendWith(LifecycleCallbacks3.class) -class PerExecutionLifecycleWithFindingFuzzTest { +class PerExecutionLifecycleWithFindingFuzzTest extends LifecycleRecordingTestBase { private static final ArrayList events = new ArrayList<>(); - private static final long RUNS = 3; - private static int nextInstanceId = 1; - private final int instanceId = nextInstanceId++; @BeforeAll static void beforeAll() { events.add("beforeAll"); } - private void addEvent(String what) { - events.add(what + " on " + instanceId); - } - - @BeforeEach - void beforeEach1() { - addEvent("beforeEach1"); - } - - @BeforeEach - void beforeEach2() { - addEvent("beforeEach2"); - } - - @BeforeEach - void beforeEach3() { - addEvent("beforeEach3"); - } - - @Disabled - @FuzzTest - void disabledFuzz(byte[] data) { - addEvent("disabledFuzz"); - throw new AssertionError("This test should not be executed"); - } - @FuzzTest(maxExecutions = RUNS, lifecycle = Lifecycle.PER_EXECUTION) void lifecycleFuzz(byte[] data) throws IOException { addEvent("lifecycleFuzz"); @@ -95,66 +43,23 @@ void lifecycleFuzz(byte[] data) throws IOException { } } - @AfterEach - void afterEach1() { - addEvent("afterEach1"); - } - - @AfterEach - void afterEach2() { - addEvent("afterEach2"); - } - - @AfterEach - void afterEach3() { - addEvent("afterEach3"); - } - - static List expectedBeforeEachEvents(int instanceId) { - return Stream.of( - "beforeEachCallback1", - "beforeEachCallback2", - "beforeEachCallback3", - "beforeEach1", - "beforeEach2", - "beforeEach3") - .map(s -> s + " on " + instanceId) - .collect(collectingAndThen(toList(), Collections::unmodifiableList)); - } - - static List expectedAfterEachEvents(int instanceId) { - return Stream.of( - "afterEach1", - "afterEach2", - "afterEach3", - "afterEachCallback3", - "afterEachCallback2", - "afterEachCallback1") - .map(s -> s + " on " + instanceId) - .collect(collectingAndThen(toList(), Collections::unmodifiableList)); - } - @AfterAll static void afterAll() throws TestSuccessfulException { events.add("afterAll"); - boolean isRegressionTest = "".equals(System.getenv("JAZZER_FUZZ")); - boolean isFuzzingFromCommandLine = System.getenv("JAZZER_FUZZ") == null; - boolean isFuzzingFromJUnit = !isFuzzingFromCommandLine && !isRegressionTest; - ArrayList expectedEvents = new ArrayList<>(); expectedEvents.add("beforeAll"); int firstFuzzingInstanceId = 1; // When run from the command-line, the fuzz test is not separately executed on the empty seed. - if (isRegressionTest || isFuzzingFromJUnit) { + if (IS_REGRESSION_TEST || IS_FUZZING_FROM_JUNIT) { expectedEvents.add("postProcessTestInstance on 1"); expectedEvents.addAll(expectedBeforeEachEvents(1)); expectedEvents.add("lifecycleFuzz on 1"); expectedEvents.addAll(expectedAfterEachEvents(1)); firstFuzzingInstanceId++; } - if (isFuzzingFromJUnit || isFuzzingFromCommandLine) { + if (IS_FUZZING_FROM_JUNIT || IS_FUZZING_FROM_COMMAND_LINE) { expectedEvents.add("postProcessTestInstance on " + firstFuzzingInstanceId); expectedEvents.addAll(expectedBeforeEachEvents(firstFuzzingInstanceId)); // The fuzz test fails during the second run. @@ -174,69 +79,8 @@ static void afterAll() throws TestSuccessfulException { throw new TestSuccessfulException("Lifecycle methods invoked as expected"); } - static void assertConsistentTestInstances(ExtensionContext extensionContext) { - assertThat(extensionContext.getTestInstance().get()) - .isSameInstanceAs(extensionContext.getRequiredTestInstance()); - assertThat(extensionContext.getTestInstances().get()) - .isSameInstanceAs(extensionContext.getRequiredTestInstances()); - assertThat(extensionContext.getRequiredTestInstances().getAllInstances()) - .containsExactly(extensionContext.getRequiredTestInstance()); - } - - static class LifecycleInstancePostProcessor implements TestInstancePostProcessor { - @Override - public void postProcessTestInstance(Object o, ExtensionContext extensionContext) { - assertThat(extensionContext.getTestInstance()).isEmpty(); - assertThat(extensionContext.getTestInstances()).isEmpty(); - ((PerExecutionLifecycleWithFindingFuzzTest) o).addEvent("postProcessTestInstance"); - } - } - - static class LifecycleCallbacks1 implements BeforeEachCallback, AfterEachCallback { - @Override - public void beforeEach(ExtensionContext extensionContext) { - assertConsistentTestInstances(extensionContext); - ((PerExecutionLifecycleWithFindingFuzzTest) extensionContext.getRequiredTestInstance()) - .addEvent("beforeEachCallback1"); - } - - @Override - public void afterEach(ExtensionContext extensionContext) { - assertConsistentTestInstances(extensionContext); - ((PerExecutionLifecycleWithFindingFuzzTest) extensionContext.getRequiredTestInstance()) - .addEvent("afterEachCallback1"); - } - } - - static class LifecycleCallbacks2 implements BeforeEachCallback, AfterEachCallback { - @Override - public void beforeEach(ExtensionContext extensionContext) { - assertConsistentTestInstances(extensionContext); - ((PerExecutionLifecycleWithFindingFuzzTest) extensionContext.getRequiredTestInstance()) - .addEvent("beforeEachCallback2"); - } - - @Override - public void afterEach(ExtensionContext extensionContext) { - assertConsistentTestInstances(extensionContext); - ((PerExecutionLifecycleWithFindingFuzzTest) extensionContext.getRequiredTestInstance()) - .addEvent("afterEachCallback2"); - } - } - - static class LifecycleCallbacks3 implements BeforeEachCallback, AfterEachCallback { - @Override - public void beforeEach(ExtensionContext extensionContext) { - assertConsistentTestInstances(extensionContext); - ((PerExecutionLifecycleWithFindingFuzzTest) extensionContext.getRequiredTestInstance()) - .addEvent("beforeEachCallback3"); - } - - @Override - public void afterEach(ExtensionContext extensionContext) { - assertConsistentTestInstances(extensionContext); - ((PerExecutionLifecycleWithFindingFuzzTest) extensionContext.getRequiredTestInstance()) - .addEvent("afterEachCallback3"); - } + @Override + protected List events() { + return events; } } diff --git a/examples/junit/src/test/java/com/example/PerTestLifecycleFuzzTest.java b/examples/junit/src/test/java/com/example/PerTestLifecycleFuzzTest.java index 43781c1be..23ae36b9c 100644 --- a/examples/junit/src/test/java/com/example/PerTestLifecycleFuzzTest.java +++ b/examples/junit/src/test/java/com/example/PerTestLifecycleFuzzTest.java @@ -17,140 +17,44 @@ package com.example; import static com.google.common.truth.Truth.assertThat; -import static com.google.common.truth.Truth8.assertThat; -import static java.util.stream.Collectors.collectingAndThen; -import static java.util.stream.Collectors.toList; import com.code_intelligence.jazzer.junit.FuzzTest; -import com.example.PerTestLifecycleFuzzTest.LifecycleCallbacks1; -import com.example.PerTestLifecycleFuzzTest.LifecycleCallbacks2; -import com.example.PerTestLifecycleFuzzTest.LifecycleCallbacks3; import java.util.ArrayList; -import java.util.Collections; import java.util.List; -import java.util.stream.Stream; import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.MethodOrderer; -import org.junit.jupiter.api.TestMethodOrder; -import org.junit.jupiter.api.extension.AfterEachCallback; -import org.junit.jupiter.api.extension.BeforeEachCallback; -import org.junit.jupiter.api.extension.ExtendWith; -import org.junit.jupiter.api.extension.ExtensionContext; -import org.junit.jupiter.api.extension.TestInstancePostProcessor; -@TestMethodOrder(MethodOrderer.MethodName.class) -@ExtendWith(PerTestLifecycleFuzzTest.LifecycleInstancePostProcessor.class) -@ExtendWith(LifecycleCallbacks1.class) -@ExtendWith(LifecycleCallbacks2.class) -@ExtendWith(LifecycleCallbacks3.class) -class PerTestLifecycleFuzzTest { +class PerTestLifecycleFuzzTest extends LifecycleRecordingTestBase { private static final ArrayList events = new ArrayList<>(); - private static final long RUNS = 3; - private static int nextInstanceId = 1; - - private final int instanceId = nextInstanceId++; @BeforeAll static void beforeAll() { events.add("beforeAll"); } - private void addEvent(String what) { - events.add(what + " on " + instanceId); - } - - @BeforeEach - void beforeEach1() { - addEvent("beforeEach1"); - } - - @BeforeEach - void beforeEach2() { - addEvent("beforeEach2"); - } - - @BeforeEach - void beforeEach3() { - addEvent("beforeEach3"); - } - - @Disabled - @FuzzTest - void disabledFuzz(byte[] data) { - addEvent("disabledFuzz"); - throw new AssertionError("This test should not be executed"); - } - @FuzzTest(maxExecutions = RUNS) void lifecycleFuzz(byte[] data) { addEvent("lifecycleFuzz"); } - @AfterEach - void afterEach1() { - addEvent("afterEach1"); - } - - @AfterEach - void afterEach2() { - addEvent("afterEach2"); - } - - @AfterEach - void afterEach3() { - addEvent("afterEach3"); - } - - static List expectedBeforeEachEvents(int instanceId) { - return Stream.of( - "beforeEachCallback1", - "beforeEachCallback2", - "beforeEachCallback3", - "beforeEach1", - "beforeEach2", - "beforeEach3") - .map(s -> s + " on " + instanceId) - .collect(collectingAndThen(toList(), Collections::unmodifiableList)); - } - - static List expectedAfterEachEvents(int instanceId) { - return Stream.of( - "afterEach1", - "afterEach2", - "afterEach3", - "afterEachCallback3", - "afterEachCallback2", - "afterEachCallback1") - .map(s -> s + " on " + instanceId) - .collect(collectingAndThen(toList(), Collections::unmodifiableList)); - } - @AfterAll static void afterAll() throws TestSuccessfulException { events.add("afterAll"); - boolean isRegressionTest = "".equals(System.getenv("JAZZER_FUZZ")); - boolean isFuzzingFromCommandLine = System.getenv("JAZZER_FUZZ") == null; - boolean isFuzzingFromJUnit = !isFuzzingFromCommandLine && !isRegressionTest; - ArrayList expectedEvents = new ArrayList<>(); expectedEvents.add("beforeAll"); // When run from the command-line, the fuzz test is not separately executed on the empty seed. int fuzzingInstanceId = 1; // When run from the command-line, the fuzz test is not separately executed on the empty seed. - if (isRegressionTest || isFuzzingFromJUnit) { + if (IS_REGRESSION_TEST || IS_FUZZING_FROM_JUNIT) { expectedEvents.add("postProcessTestInstance on 1"); expectedEvents.addAll(expectedBeforeEachEvents(1)); expectedEvents.add("lifecycleFuzz on 1"); expectedEvents.addAll(expectedAfterEachEvents(1)); fuzzingInstanceId++; } - if (isFuzzingFromJUnit || isFuzzingFromCommandLine) { + if (IS_FUZZING_FROM_JUNIT || IS_FUZZING_FROM_COMMAND_LINE) { // With the PER_TEST lifecycle, fuzzing uses the instance provided by JUnit for all // executions. expectedEvents.add("postProcessTestInstance on " + fuzzingInstanceId); @@ -167,69 +71,8 @@ static void afterAll() throws TestSuccessfulException { throw new TestSuccessfulException("Lifecycle methods invoked as expected"); } - static void assertConsistentTestInstances(ExtensionContext extensionContext) { - assertThat(extensionContext.getTestInstance().get()) - .isSameInstanceAs(extensionContext.getRequiredTestInstance()); - assertThat(extensionContext.getTestInstances().get()) - .isSameInstanceAs(extensionContext.getRequiredTestInstances()); - assertThat(extensionContext.getRequiredTestInstances().getAllInstances()) - .containsExactly(extensionContext.getRequiredTestInstance()); - } - - static class LifecycleInstancePostProcessor implements TestInstancePostProcessor { - @Override - public void postProcessTestInstance(Object o, ExtensionContext extensionContext) { - assertThat(extensionContext.getTestInstance()).isEmpty(); - assertThat(extensionContext.getTestInstances()).isEmpty(); - ((PerTestLifecycleFuzzTest) o).addEvent("postProcessTestInstance"); - } - } - - static class LifecycleCallbacks1 implements BeforeEachCallback, AfterEachCallback { - @Override - public void beforeEach(ExtensionContext extensionContext) { - assertConsistentTestInstances(extensionContext); - ((PerTestLifecycleFuzzTest) extensionContext.getRequiredTestInstance()) - .addEvent("beforeEachCallback1"); - } - - @Override - public void afterEach(ExtensionContext extensionContext) { - assertConsistentTestInstances(extensionContext); - ((PerTestLifecycleFuzzTest) extensionContext.getRequiredTestInstance()) - .addEvent("afterEachCallback1"); - } - } - - static class LifecycleCallbacks2 implements BeforeEachCallback, AfterEachCallback { - @Override - public void beforeEach(ExtensionContext extensionContext) { - assertConsistentTestInstances(extensionContext); - ((PerTestLifecycleFuzzTest) extensionContext.getRequiredTestInstance()) - .addEvent("beforeEachCallback2"); - } - - @Override - public void afterEach(ExtensionContext extensionContext) { - assertConsistentTestInstances(extensionContext); - ((PerTestLifecycleFuzzTest) extensionContext.getRequiredTestInstance()) - .addEvent("afterEachCallback2"); - } - } - - static class LifecycleCallbacks3 implements BeforeEachCallback, AfterEachCallback { - @Override - public void beforeEach(ExtensionContext extensionContext) { - assertConsistentTestInstances(extensionContext); - ((PerTestLifecycleFuzzTest) extensionContext.getRequiredTestInstance()) - .addEvent("beforeEachCallback3"); - } - - @Override - public void afterEach(ExtensionContext extensionContext) { - assertConsistentTestInstances(extensionContext); - ((PerTestLifecycleFuzzTest) extensionContext.getRequiredTestInstance()) - .addEvent("afterEachCallback3"); - } + @Override + protected List events() { + return events; } }