Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce a way to disable integration tests for certain build types #25025

Merged
merged 2 commits into from
Apr 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package io.quarkus.test.junit;

public final class ArtifactTypeUtil {

private ArtifactTypeUtil() {
}

public static boolean isContainer(String artifactType) {
return "jar-container".equals(artifactType) || "native-container".equals(artifactType);
}

public static boolean isNativeBinary(String artifactType) {
return "native".equals(artifactType);
}

public static boolean isJar(String artifactType) {
return "jar".equals(artifactType);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,18 @@
* Reason for disabling this test
*/
String value() default "";

/**
* The types of Quarkus application produced by the build for which this test is disabled.
* For example, if the tests are supposed to be disabled for built containers only,
* {@code ArtifactType.CONTAINER} would be set.
*/
ArtifactType[] forArtifactTypes() default { ArtifactType.ALL };

enum ArtifactType {
ALL,
JAR,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mind adding javadocs to the corresponding type-strings (like fast-jar, uber-jar, etc)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really want to do this, as these strings are internal and not meant to be used by anyone but the testing facility

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Meant the values for quarkus.package.type

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That information isn't available at this point and in any case, for tests it should not make a difference - I mean in what scenario would want to only not execute a test if it's for an uber-jar for example?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thought it could be useful information for users to associate quarkus.package.type=fast-jar with the JAR enum value.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(javadoc)

CONTAINER,
NATIVE_BINARY,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be nice to have NATIVE_CONTAINER + JAR_CONTAINER as well

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How come? Is there a reason you would want to run tests for jar container and not a native container?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe. Could think of a configuration/profile that uses an on-heap cache (e.g. caffeine) with an uber-jar, but no cache with a native image (because caches are not sooo great with serial GC in native images from GraalVM community).

Copy link
Contributor Author

@geoand geoand Apr 20, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would rather not do this unless we have a real need for it

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay

}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
package io.quarkus.test.junit;

import static io.quarkus.test.junit.ArtifactTypeUtil.isContainer;
import static io.quarkus.test.junit.ArtifactTypeUtil.isJar;
import static io.quarkus.test.junit.ArtifactTypeUtil.isNativeBinary;
import static io.quarkus.test.junit.DisabledOnIntegrationTest.ArtifactType.ALL;
import static io.quarkus.test.junit.DisabledOnIntegrationTest.ArtifactType.CONTAINER;
import static io.quarkus.test.junit.DisabledOnIntegrationTest.ArtifactType.JAR;
import static io.quarkus.test.junit.DisabledOnIntegrationTest.ArtifactType.NATIVE_BINARY;
import static io.quarkus.test.junit.IntegrationTestUtil.getArtifactType;
import static io.quarkus.test.junit.IntegrationTestUtil.readQuarkusArtifactProperties;
import static org.junit.platform.commons.util.AnnotationUtils.findAnnotation;

import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.util.Optional;
import java.util.function.BiFunction;
import java.util.function.Function;

import org.junit.jupiter.api.extension.ConditionEvaluationResult;
Expand All @@ -27,31 +37,53 @@ public class DisabledOnIntegrationTestCondition implements ExecutionCondition {
public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) {
Optional<AnnotatedElement> element = context.getElement();
ConditionEvaluationResult disabledOnIntegrationTestReason = check(context, element, DisabledOnIntegrationTest.class,
DisabledOnIntegrationTest::value);
DisabledOnIntegrationTest::value,
// check and see if the artifact type of the build has been disabled
((ec, an) -> {
DisabledOnIntegrationTest.ArtifactType[] disabledArtifactTypes = an.forArtifactTypes();
String artifactType = getArtifactType(readQuarkusArtifactProperties(ec));
for (DisabledOnIntegrationTest.ArtifactType disabledArtifactType : disabledArtifactTypes) {
if (disabledArtifactType == ALL) {
return true;
}
if ((disabledArtifactType == CONTAINER) && isContainer(artifactType)) {
return true;
}
if ((disabledArtifactType == NATIVE_BINARY) && isNativeBinary(artifactType)) {
return true;
}
if ((disabledArtifactType == JAR) && isJar(artifactType)) {
return true;
}
}
return false;
}));
if (disabledOnIntegrationTestReason != null) {
return disabledOnIntegrationTestReason;
}
// support DisabledOnNativeImage for backward compatibility
ConditionEvaluationResult disabledOnNativeImageReason = check(context, element, DisabledOnNativeImage.class,
DisabledOnNativeImage::value);
DisabledOnNativeImage::value, null);
if (disabledOnNativeImageReason != null) {
return disabledOnNativeImageReason;
}
return ENABLED;
}

private <T extends Annotation> ConditionEvaluationResult check(ExtensionContext context, Optional<AnnotatedElement> element,
Class<T> annotationClass, Function<T, String> valueExtractor) {
Class<T> annotationClass, Function<T, String> valueExtractor, BiFunction<ExtensionContext, T, Boolean> predicate) {
Optional<T> disabled = findAnnotation(element, annotationClass);
if (disabled.isPresent()) {
// Cannot use ExtensionState here because this condition needs to be evaluated before QuarkusTestExtension
boolean it = findAnnotation(context.getTestClass(), QuarkusIntegrationTest.class).isPresent()
|| findAnnotation(context.getTestClass(), QuarkusMainIntegrationTest.class).isPresent();
if (it) {
String reason = disabled.map(valueExtractor)
.filter(StringUtils::isNotBlank)
.orElseGet(() -> element.get() + " is @DisabledOnIntegrationTest");
return ConditionEvaluationResult.disabled(reason);
if ((predicate == null) || predicate.apply(context, disabled.get())) {
String reason = disabled.map(valueExtractor)
.filter(StringUtils::isNotBlank)
.orElseGet(() -> element.get() + " is @DisabledOnIntegrationTest");
return ConditionEvaluationResult.disabled(reason);
}
}
}
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,14 @@
* {@code @BeforeEach} methods, {@code @AfterEach} methods, and corresponding
* extension APIs.
*
* @deprecated Use {@link @DisabledOnIntegrationTest} instead.
*
*/
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Deprecated(since = "2.9.0.Final", forRemoval = true)
public @interface DisabledOnNativeImage {
/**
* Reason for disabling this test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,14 @@ static Properties readQuarkusArtifactProperties(ExtensionContext context) {
}
}

static String getArtifactType(Properties quarkusArtifactProperties) {
String artifactType = quarkusArtifactProperties.getProperty("type");
if (artifactType == null) {
throw new IllegalStateException("Unable to determine the type of artifact created by the Quarkus build");
}
return artifactType;
}

private static TestLauncher determineTestLauncher() {
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
int i = stackTrace.length - 1;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package io.quarkus.test.junit;

import static io.quarkus.test.junit.ArtifactTypeUtil.isContainer;
import static io.quarkus.test.junit.IntegrationTestUtil.activateLogging;
import static io.quarkus.test.junit.IntegrationTestUtil.determineBuildOutputDirectory;
import static io.quarkus.test.junit.IntegrationTestUtil.determineTestProfileAndProperties;
import static io.quarkus.test.junit.IntegrationTestUtil.doProcessTestInstance;
import static io.quarkus.test.junit.IntegrationTestUtil.ensureNoInjectAnnotationIsUsed;
import static io.quarkus.test.junit.IntegrationTestUtil.findProfile;
import static io.quarkus.test.junit.IntegrationTestUtil.getAdditionalTestResources;
import static io.quarkus.test.junit.IntegrationTestUtil.getArtifactType;
import static io.quarkus.test.junit.IntegrationTestUtil.getSysPropsToRestore;
import static io.quarkus.test.junit.IntegrationTestUtil.handleDevServices;
import static io.quarkus.test.junit.IntegrationTestUtil.readQuarkusArtifactProperties;
Expand Down Expand Up @@ -132,12 +134,9 @@ private IntegrationTestExtensionState ensureStarted(ExtensionContext extensionCo
private IntegrationTestExtensionState doProcessStart(Properties quarkusArtifactProperties,
Class<? extends QuarkusTestProfile> profile, ExtensionContext context)
throws Throwable {
String artifactType = quarkusArtifactProperties.getProperty("type");
if (artifactType == null) {
throw new IllegalStateException("Unable to determine the type of artifact created by the Quarkus build");
}
String artifactType = getArtifactType(quarkusArtifactProperties);

boolean isDockerLaunch = "jar-container".equals(artifactType) || "native-container".equals(artifactType);
boolean isDockerLaunch = isContainer(artifactType);

ArtifactLauncher.InitContext.DevServicesLaunchResult devServicesLaunchResult = handleDevServices(context,
isDockerLaunch);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.quarkus.test.junit.launcher;

import static io.quarkus.test.junit.ArtifactTypeUtil.isContainer;
import static io.quarkus.test.junit.IntegrationTestUtil.DEFAULT_HTTPS_PORT;
import static io.quarkus.test.junit.IntegrationTestUtil.DEFAULT_PORT;

Expand All @@ -22,7 +23,7 @@ public class DockerContainerLauncherProvider implements ArtifactLauncherProvider

@Override
public boolean supportsArtifactType(String type) {
return "jar-container".equals(type) || "native-container".equals(type);
return isContainer(type);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.quarkus.test.junit.launcher;

import static io.quarkus.test.junit.ArtifactTypeUtil.isJar;
import static io.quarkus.test.junit.IntegrationTestUtil.DEFAULT_HTTPS_PORT;
import static io.quarkus.test.junit.IntegrationTestUtil.DEFAULT_PORT;

Expand All @@ -21,7 +22,7 @@ public class JarLauncherProvider implements ArtifactLauncherProvider {

@Override
public boolean supportsArtifactType(String type) {
return "jar".equals(type);
return isJar(type);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.quarkus.test.junit.launcher;

import static io.quarkus.test.junit.ArtifactTypeUtil.isNativeBinary;
import static io.quarkus.test.junit.IntegrationTestUtil.DEFAULT_HTTPS_PORT;
import static io.quarkus.test.junit.IntegrationTestUtil.DEFAULT_PORT;

Expand All @@ -19,7 +20,7 @@
public class NativeImageLauncherProvider implements ArtifactLauncherProvider {
@Override
public boolean supportsArtifactType(String type) {
return "native".equals(type);
return isNativeBinary(type);
}

@Override
Expand Down