Skip to content

Commit

Permalink
tests: Extract common base class out of lifecycle tests
Browse files Browse the repository at this point in the history
  • Loading branch information
fmeum committed Oct 18, 2023
1 parent 55eb18b commit 13a7c77
Show file tree
Hide file tree
Showing 5 changed files with 224 additions and 488 deletions.
15 changes: 15 additions & 0 deletions examples/junit/src/test/java/com/example/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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",
Expand All @@ -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",
Expand Down Expand Up @@ -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 = [
Expand Down
Original file line number Diff line number Diff line change
@@ -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<String> events();

static List<String> expectedBeforeEachEvents(int instanceId) {
return Stream.of(
"beforeEachCallback1",
"beforeEachCallback2",
"beforeEachCallback3",
"beforeEach1",
"beforeEach2",
"beforeEach3")
.map(s -> s + " on " + instanceId)
.collect(collectingAndThen(toList(), Collections::unmodifiableList));
}

static List<String> 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");
}
}
}
Loading

0 comments on commit 13a7c77

Please sign in to comment.