From 9b3c21225dbd326447409ab5a7f9aae05bfc43d6 Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Tue, 20 Aug 2024 11:24:13 +0200 Subject: [PATCH] Support arbitrary Java versions with JRE conditions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit introduces support for arbitrary Java versions in the JRE enum, @⁠EnabledOnJre, @⁠DisabledOnJre, @⁠EnabledForJreRange, and @⁠DisabledForJreRange. Closes: #3930 --- .../example/ConditionalTestExecutionDemo.java | 53 +++++ .../api/condition/DisabledForJreRange.java | 76 ++++-- .../DisabledForJreRangeCondition.java | 12 +- .../jupiter/api/condition/DisabledOnJre.java | 31 ++- .../api/condition/DisabledOnJreCondition.java | 9 +- .../api/condition/EnabledForJreRange.java | 76 ++++-- .../EnabledForJreRangeCondition.java | 53 ++++- .../jupiter/api/condition/EnabledOnJre.java | 33 ++- .../api/condition/EnabledOnJreCondition.java | 9 +- .../junit/jupiter/api/condition/JRE.java.jte | 138 +++++++++-- .../DisabledOnJreConditionTests.java.jte | 29 ++- .../DisabledOnJreIntegrationTests.java.jte | 14 +- .../EnabledOnJreConditionTests.java.jte | 29 ++- .../EnabledOnJreIntegrationTests.java.jte | 14 +- .../AbstractExecutionConditionTests.java | 2 +- .../DisabledForJreRangeConditionTests.java | 9 +- .../EnabledForJreRangeConditionTests.java | 217 ++++++++++++++++-- .../EnabledForJreRangeIntegrationTests.java | 197 ++++++++++++++-- .../junit/jupiter/api/condition/JRETests.java | 110 +++++++-- .../support/tests/JavaVersionsTests.java | 2 +- .../support/tests/MultiReleaseJarTests.java | 2 +- .../tests/UnalignedClasspathTests.java | 2 +- 22 files changed, 956 insertions(+), 161 deletions(-) diff --git a/documentation/src/test/java/example/ConditionalTestExecutionDemo.java b/documentation/src/test/java/example/ConditionalTestExecutionDemo.java index 5d9e68eaa5a4..5271570fa732 100644 --- a/documentation/src/test/java/example/ConditionalTestExecutionDemo.java +++ b/documentation/src/test/java/example/ConditionalTestExecutionDemo.java @@ -12,6 +12,8 @@ import static org.junit.jupiter.api.condition.JRE.JAVA_10; import static org.junit.jupiter.api.condition.JRE.JAVA_11; +import static org.junit.jupiter.api.condition.JRE.JAVA_17; +import static org.junit.jupiter.api.condition.JRE.JAVA_18; import static org.junit.jupiter.api.condition.JRE.JAVA_8; import static org.junit.jupiter.api.condition.JRE.JAVA_9; import static org.junit.jupiter.api.condition.OS.LINUX; @@ -23,6 +25,7 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledForJreRange; import org.junit.jupiter.api.condition.DisabledIf; @@ -38,6 +41,7 @@ import org.junit.jupiter.api.condition.EnabledInNativeImage; import org.junit.jupiter.api.condition.EnabledOnJre; import org.junit.jupiter.api.condition.EnabledOnOs; +import org.junit.jupiter.api.condition.JRE; class ConditionalTestExecutionDemo { @@ -99,6 +103,16 @@ void notOnNewMacs() { } // end::user_guide_architecture[] + @Test + @EnabledOnJre(value = { JAVA_17, JAVA_18 }, versions = { 20, 21 }) + void onJava17or18or20or21() { + } + + @Test + @EnabledOnJre(versions = 21) + void onlyOnJava21() { + } + // tag::user_guide_jre[] @Test @EnabledOnJre(JAVA_8) @@ -124,6 +138,45 @@ void fromJava9toCurrentJavaFeatureNumber() { // ... } + @Test + @EnabledForJreRange(minVersion = 10) + void fromJava10toCurrentJavaFeatureNumber() { + // ... + } + + @Test + @EnabledForJreRange(minVersion = 25) + void fromJava25toCurrentJavaFeatureNumber() { + // ... + } + + @Disabled("DEMO: intended to fail") + @Test + @EnabledForJreRange(minVersion = 99, max = JRE.JAVA_17) + void fromJava99toJava17() { + // ... + } + + @Disabled("DEMO: intended to fail") + @Test + @EnabledForJreRange(min = JAVA_11, minVersion = 10) + void competingJreAndMinVersions() { + // ... + } + + @Disabled("DEMO: intended to fail") + @Test + @EnabledForJreRange(max = JAVA_11, maxVersion = 10) + void competingJreAndMaxVersions() { + // ... + } + + @Test + @EnabledForJreRange(minVersion = 10, maxVersion = 25) + void fromJava17to25() { + // ... + } + @Test @EnabledForJreRange(max = JAVA_11) void fromJava8To11() { diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledForJreRange.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledForJreRange.java index fc96d82118b0..aa83fe01a34d 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledForJreRange.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledForJreRange.java @@ -10,6 +10,7 @@ package org.junit.jupiter.api.condition; +import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; @@ -24,7 +25,10 @@ /** * {@code @DisabledForJreRange} is used to signal that the annotated test class * or test method is disabled for a specific range of Java Runtime - * Environment (JRE) versions from {@link #min} to {@link #max}. + * Environment (JRE) versions. + * + *

Version ranges can be specified as {@link JRE} enum constants via {@link #min} + * and {@link #max} or as integers via {@link #minVersion} and {@link #maxVersion}. * *

When applied at the class level, all test methods within that class will * be disabled on the same specified JRE versions. @@ -82,28 +86,74 @@ public @interface DisabledForJreRange { /** - * Java Runtime Environment version which is used as the lower boundary - * for the version range that determines if the annotated class or method - * should be disabled. + * Java Runtime Environment version which is used as the lower boundary for + * the version range that determines if the annotated class or method should + * be disabled, specified as a {@link JRE} enum constant. + * + *

If a {@code JRE} enum constant does not exist for a particular JRE + * version, you can specify the minimum version via {@link #minVersion()} + * instead. * - *

Defaults to {@link JRE#JAVA_8 JAVA_8}, as this is the lowest - * supported JRE version. + *

Defaults to {@link JRE#UNDEFINED UNDEFINED}, which will be interpreted + * as {@link JRE#JAVA_8 JAVA_8} if the {@link #minVersion()} is not set. * * @see JRE + * @see #minVersion() */ - JRE min() default JRE.JAVA_8; + JRE min() default JRE.UNDEFINED; /** - * Java Runtime Environment version which is used as the upper boundary - * for the version range that determines if the annotated class or method - * should be disabled. + * Java Runtime Environment version which is used as the upper boundary for + * the version range that determines if the annotated class or method should + * be disabled, specified as a {@link JRE} enum constant. * - *

Defaults to {@link JRE#OTHER OTHER}, as this will always be the highest - * possible version. + *

If a {@code JRE} enum constant does not exist for a particular JRE + * version, you can specify the maximum version via {@link #maxVersion()} + * instead. + * + *

Defaults to {@link JRE#UNDEFINED UNDEFINED}, which will be interpreted + * as {@link JRE#OTHER OTHER} if the {@link #maxVersion()} is not set. * * @see JRE + * @see #maxVersion() + */ + JRE max() default JRE.UNDEFINED; + + /** + * Java Runtime Environment version which is used as the lower boundary for + * the version range that determines if the annotated class or method should + * be disabled, specified as an integer. + * + *

If a {@code JRE} enum constant exists for the particular JRE version, + * you can specify the minimum version via {@link #min()} instead. + * + *

Defaults to {@code -1} to signal that {@link #min()} should be used instead. + * + * @since 5.12 + * @see #min() + * @see JRE#featureVersion() + * @see Runtime.Version#feature() + */ + @API(status = EXPERIMENTAL, since = "5.12") + int minVersion() default -1; + + /** + * Java Runtime Environment version which is used as the upper boundary for + * the version range that determines if the annotated class or method should + * be disabled, specified as an integer. + * + *

If a {@code JRE} enum constant exists for the particular JRE version, + * you can specify the maximum version via {@link #max()} instead. + * + *

Defaults to {@code -1} to signal that {@link #max()} should be used instead. + * + * @since 5.12 + * @see #max() + * @see JRE#featureVersion() + * @see Runtime.Version#feature() */ - JRE max() default JRE.OTHER; + @API(status = EXPERIMENTAL, since = "5.12") + int maxVersion() default -1; /** * Custom reason to provide if the test or container is disabled. diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledForJreRangeCondition.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledForJreRangeCondition.java index b62e7053c4de..bf859d2b877e 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledForJreRangeCondition.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledForJreRangeCondition.java @@ -14,7 +14,6 @@ import static org.junit.jupiter.api.condition.EnabledOnJreCondition.ENABLED_ON_CURRENT_JRE; import org.junit.jupiter.api.extension.ExecutionCondition; -import org.junit.platform.commons.util.Preconditions; /** * {@link ExecutionCondition} for {@link DisabledForJreRange @DisabledForJreRange}. @@ -31,15 +30,8 @@ class DisabledForJreRangeCondition extends BooleanExecutionCondition= 0, - "@DisabledForJreRange.min must be less than or equal to @DisabledForJreRange.max"); - - return !JRE.isCurrentVersionWithinRange(min, max); + return !EnabledForJreRangeCondition.isCurrentVersionWithinRange("DisabledForJreRange", annotation.min(), + annotation.max(), annotation.minVersion(), annotation.maxVersion()); } } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledOnJre.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledOnJre.java index 6231f5246067..8b06ea87ac13 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledOnJre.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledOnJre.java @@ -10,6 +10,7 @@ package org.junit.jupiter.api.condition; +import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; @@ -24,7 +25,10 @@ /** * {@code @DisabledOnJre} is used to signal that the annotated test class or * test method is disabled on one or more specified Java Runtime - * Environment (JRE) {@linkplain #value versions}. + * Environment (JRE) versions. + * + *

Versions can be specified as {@link JRE} enum constants via {@link #value()} + * or as integers via {@link #versions()}. * *

When applied at the class level, all test methods within that class * will be disabled on the same specified JRE versions. @@ -82,12 +86,31 @@ public @interface DisabledOnJre { /** - * Java Runtime Environment versions on which the annotated class or - * method should be disabled. + * Java Runtime Environment versions on which the annotated class or method + * should be disabled, specified as {@link JRE} enum constants. + * + *

If a {@code JRE} enum constant does not exist for a particular JRE + * version, you can specify the version via {@link #versions()} instead. * * @see JRE + * @see #versions() + */ + JRE[] value() default {}; + + /** + * Java Runtime Environment versions on which the annotated class or method + * should be disabled, specified as integers. + * + *

If a {@code JRE} enum constant exists for a particular JRE version, you + * can specify the version via {@link #value()} instead. + * + * @since 5.12 + * @see #value() + * @see JRE#featureVersion() + * @see Runtime.Version#feature() */ - JRE[] value(); + @API(status = EXPERIMENTAL, since = "5.12") + int[] versions() default {}; /** * Custom reason to provide if the test or container is disabled. diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledOnJreCondition.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledOnJreCondition.java index aa74770bc3cd..d66bfe062c08 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledOnJreCondition.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledOnJreCondition.java @@ -32,9 +32,12 @@ class DisabledOnJreCondition extends BooleanExecutionCondition { @Override boolean isEnabled(DisabledOnJre annotation) { - JRE[] versions = annotation.value(); - Preconditions.condition(versions.length > 0, "You must declare at least one JRE in @DisabledOnJre"); - return Arrays.stream(versions).noneMatch(JRE::isCurrentVersion); + JRE[] jres = annotation.value(); + int[] featureVersions = annotation.versions(); + Preconditions.condition(jres.length > 0 || featureVersions.length > 0, + "You must declare at least one JRE or version in @DisabledOnJre"); + return Arrays.stream(jres).noneMatch(JRE::isCurrentVersion) + && Arrays.stream(featureVersions).noneMatch(JRE::isCurrentVersion); } } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledForJreRange.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledForJreRange.java index 79ef2aeb595e..268d6fefcb24 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledForJreRange.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledForJreRange.java @@ -10,6 +10,7 @@ package org.junit.jupiter.api.condition; +import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; @@ -24,7 +25,10 @@ /** * {@code @EnabledForJreRange} is used to signal that the annotated test class or * test method is only enabled for a specific range of Java Runtime - * Environment (JRE) versions from {@link #min} to {@link #max}. + * Environment (JRE) versions. + * + *

Version ranges can be specified as {@link JRE} enum constants via {@link #min} + * and {@link #max} or as integers via {@link #minVersion} and {@link #maxVersion}. * *

When applied at the class level, all test methods within that class will * be enabled on the same specified JRE versions. @@ -82,28 +86,74 @@ public @interface EnabledForJreRange { /** - * Java Runtime Environment version which should be used as the lower boundary - * for the version range that determines if the annotated class or method - * should be enabled. + * Java Runtime Environment version which is used as the lower boundary for + * the version range that determines if the annotated class or method should + * be enabled, specified as a {@link JRE} enum constant. + * + *

If a {@code JRE} enum constant does not exist for a particular JRE + * version, you can specify the minimum version via {@link #minVersion()} + * instead. * - *

Defaults to {@link JRE#JAVA_8 JAVA_8}, as this is the lowest - * supported JRE version. + *

Defaults to {@link JRE#UNDEFINED UNDEFINED}, which will be interpreted + * as {@link JRE#JAVA_8 JAVA_8} if the {@link #minVersion()} is not set. * * @see JRE + * @see #minVersion() */ - JRE min() default JRE.JAVA_8; + JRE min() default JRE.UNDEFINED; /** - * Java Runtime Environment version which should be used as the upper boundary - * for the version range that determines if the annotated class or method - * should be enabled. + * Java Runtime Environment version which is used as the upper boundary for + * the version range that determines if the annotated class or method should + * be enabled, specified as a {@link JRE} enum constant. * - *

Defaults to {@link JRE#OTHER OTHER}, as this will always be the highest - * possible version. + *

If a {@code JRE} enum constant does not exist for a particular JRE + * version, you can specify the maximum version via {@link #maxVersion()} + * instead. + * + *

Defaults to {@link JRE#UNDEFINED UNDEFINED}, which will be interpreted + * as {@link JRE#OTHER OTHER} if the {@link #maxVersion()} is not set. * * @see JRE + * @see #maxVersion() + */ + JRE max() default JRE.UNDEFINED; + + /** + * Java Runtime Environment version which is used as the lower boundary for + * the version range that determines if the annotated class or method should + * be enabled, specified as an integer. + * + *

If a {@code JRE} enum constant exists for the particular JRE version, + * you can specify the minimum version via {@link #min()} instead. + * + *

Defaults to {@code -1} to signal that {@link #min()} should be used instead. + * + * @since 5.12 + * @see #min() + * @see JRE#featureVersion() + * @see Runtime.Version#feature() + */ + @API(status = EXPERIMENTAL, since = "5.12") + int minVersion() default -1; + + /** + * Java Runtime Environment version which is used as the upper boundary for + * the version range that determines if the annotated class or method should + * be enabled, specified as an integer. + * + *

If a {@code JRE} enum constant exists for the particular JRE version, + * you can specify the maximum version via {@link #max()} instead. + * + *

Defaults to {@code -1} to signal that {@link #max()} should be used instead. + * + * @since 5.12 + * @see #max() + * @see JRE#featureVersion() + * @see Runtime.Version#feature() */ - JRE max() default JRE.OTHER; + @API(status = EXPERIMENTAL, since = "5.12") + int maxVersion() default -1; /** * Custom reason to provide if the test or container is disabled. diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledForJreRangeCondition.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledForJreRangeCondition.java index abb5001a7ccf..e606d98344d0 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledForJreRangeCondition.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledForJreRangeCondition.java @@ -31,13 +31,54 @@ class EnabledForJreRangeCondition extends BooleanExecutionCondition String.format( + "@%s's minimum value must be configured with either a JRE enum constant or numeric version, but not both", + annotationName)); + Preconditions.condition(!maxJreSet || !maxVersionSet, () -> String.format( + "@%s's maximum value must be configured with either a JRE enum constant or numeric version, but not both", + annotationName)); + + // Users must supply valid values for minVersion and maxVersion. + Preconditions.condition(!minVersionSet || (minVersion >= 8), + () -> String.format("@%s's minVersion [%d] must be greater than or equal to 8", annotationName, + minVersion)); + Preconditions.condition(!maxVersionSet || (maxVersion >= 8), + () -> String.format("@%s's maxVersion [%d] must be greater than or equal to 8", annotationName, + maxVersion)); + + // Users must supply at least one non-default value. + Preconditions.condition(minJreSet || minVersionSet || maxJreSet || maxVersionSet, + () -> "You must declare a non-default value for the minimum or maximum value in @" + annotationName); + + // Now that we have checked all preconditions, we need to ensure that we are + // using valid JRE enum constants. + if (!minJreSet) { + minJre = JRE.JAVA_8; + } + if (!maxJreSet) { + maxJre = JRE.OTHER; + } - Preconditions.condition((min != JRE.JAVA_8 || max != JRE.OTHER), - "You must declare a non-default value for min or max in @EnabledForJreRange"); - Preconditions.condition(max.compareTo(min) >= 0, - "@EnabledForJreRange.min must be less than or equal to @EnabledForJreRange.max"); + int min = (minVersionSet ? minVersion : minJre.version()); + int max = (maxVersionSet ? maxVersion : maxJre.version()); + Preconditions.condition(min >= 8, + () -> String.format("@%s's minimum value [%d] must greater than or equal to 8", annotationName, min)); + Preconditions.condition(min <= max, + () -> String.format("@%s's minimum value [%d] must be less than or equal to its maximum value [%d]", + annotationName, min, max)); return JRE.isCurrentVersionWithinRange(min, max); } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledOnJre.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledOnJre.java index f768e439c18f..119efadc7f3f 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledOnJre.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledOnJre.java @@ -10,6 +10,7 @@ package org.junit.jupiter.api.condition; +import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; @@ -23,8 +24,11 @@ /** * {@code @EnabledOnJre} is used to signal that the annotated test class or - * test method is only enabled on one or more specified Java - * Runtime Environment (JRE) {@linkplain #value versions}. + * test method is only enabled on one or more specified Java Runtime + * Environment (JRE) versions. + * + *

Versions can be specified as {@link JRE} enum constants via {@link #value()} + * or as integers via {@link #versions()}. * *

When applied at the class level, all test methods within that class * will be enabled on the same specified JRE versions. @@ -82,12 +86,31 @@ public @interface EnabledOnJre { /** - * Java Runtime Environment versions on which the annotated class or - * method should be enabled. + * Java Runtime Environment versions on which the annotated class or method + * should be enabled, specified as {@link JRE} enum constants. + * + *

If a {@code JRE} enum constant does not exist for a particular JRE + * version, you can specify the version via {@link #versions()} instead. * * @see JRE + * @see #versions() + */ + JRE[] value() default {}; + + /** + * Java Runtime Environment versions on which the annotated class or method + * should be enabled, specified as integers. + * + *

If a {@code JRE} enum constant exists for a particular JRE version, you + * can specify the version via {@link #value()} instead. + * + * @since 5.12 + * @see #value() + * @see JRE#featureVersion() + * @see Runtime.Version#feature() */ - JRE[] value(); + @API(status = EXPERIMENTAL, since = "5.12") + int[] versions() default {}; /** * Custom reason to provide if the test or container is disabled. diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledOnJreCondition.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledOnJreCondition.java index 674d0687856c..c1765d52adfb 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledOnJreCondition.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledOnJreCondition.java @@ -35,9 +35,12 @@ class EnabledOnJreCondition extends BooleanExecutionCondition { @Override boolean isEnabled(EnabledOnJre annotation) { - JRE[] versions = annotation.value(); - Preconditions.condition(versions.length > 0, "You must declare at least one JRE in @EnabledOnJre"); - return Arrays.stream(versions).anyMatch(JRE::isCurrentVersion); + JRE[] jres = annotation.value(); + int[] featureVersions = annotation.versions(); + Preconditions.condition(jres.length > 0 || featureVersions.length > 0, + "You must declare at least one JRE or version in @EnabledOnJre"); + return Arrays.stream(jres).anyMatch(JRE::isCurrentVersion) + || Arrays.stream(featureVersions).anyMatch(JRE::isCurrentVersion); } } diff --git a/junit-jupiter-api/src/templates/resources/main/org/junit/jupiter/api/condition/JRE.java.jte b/junit-jupiter-api/src/templates/resources/main/org/junit/jupiter/api/condition/JRE.java.jte index 93479da1378f..38aa0f82ce7c 100644 --- a/junit-jupiter-api/src/templates/resources/main/org/junit/jupiter/api/condition/JRE.java.jte +++ b/junit-jupiter-api/src/templates/resources/main/org/junit/jupiter/api/condition/JRE.java.jte @@ -7,10 +7,11 @@ ${licenseHeader} package org.junit.jupiter.api.condition; +import static org.apiguardian.api.API.Status.DEPRECATED; +import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.STABLE; import java.lang.reflect.Method; -import java.util.EnumSet; import org.apiguardian.api.API; import org.junit.platform.commons.logging.Logger; @@ -38,6 +39,19 @@ import org.junit.platform.commons.util.StringUtils; */ @API(status = STABLE, since = "5.1") public enum JRE { + + /** + * An undefined JRE version. + * + *

This constant is used by JUnit as a default configuration value but is + * not intended to be used by users. + * + *

This constant returns {@code -1} for its {@link #version() version}. + * + * @since 5.12 + */ + @API(status = EXPERIMENTAL, since = "5.12") + UNDEFINED(-1), @for(var jre : jres) /** * Java ${jre.getVersion()}. @@ -49,7 +63,7 @@ public enum JRE { @if(jre.getSince() != null)<%-- --%>@API(status = STABLE, since = "${jre.getSince()}") @endif<%-- ---%>JAVA_${jre.getVersion()}, +--%>JAVA_${jre.getVersion()}(${jre.getVersion()}), @endfor /** * A JRE version other than <%-- @@ -60,14 +74,21 @@ public enum JRE { --%>@if(jre.getIndex() % 3 == 1 && !jre.isLast()) * @elseif(!jre.isLast()) @endif<%-- --%>@endfor + * + *

This constant returns {@link Integer#MAX_VALUE} for its + * {@link #version() version}. */ - OTHER; + OTHER(Integer.MAX_VALUE); + + static final int UNDEFINED_VERSION = -1; private static final Logger logger = LoggerFactory.getLogger(JRE.class); - private static final JRE CURRENT_VERSION = determineCurrentVersion(); + private static final int CURRENT_VERSION = determineCurrentVersion(); - private static JRE determineCurrentVersion() { + private static final JRE CURRENT_JRE = determineCurrentJre(CURRENT_VERSION); + + private static int determineCurrentVersion() { String javaVersion = System.getProperty("java.version"); boolean javaVersionIsBlank = StringUtils.isBlank(javaVersion); @@ -77,7 +98,7 @@ public enum JRE { } if (!javaVersionIsBlank && javaVersion.startsWith("1.8")) { - return JAVA_8; + return 8; } try { @@ -87,33 +108,62 @@ public enum JRE { Method versionMethod = Runtime.class.getMethod("version"); Object version = ReflectionSupport.invokeMethod(versionMethod, null); Method majorMethod = version.getClass().getMethod("major"); - int major = (int) ReflectionSupport.invokeMethod(majorMethod, version); - switch (major) {<%-- - --%>@for(var jre : jres)<%-- - --%>@if(jre.getVersion() != 8) - case ${jre.getVersion()}: - return JAVA_${jre.getVersion()};<%-- - --%>@endif<%-- - --%>@endfor - default: - return OTHER; - } + return (int) ReflectionSupport.invokeMethod(majorMethod, version); } catch (Exception ex) { logger.debug(ex, () -> "Failed to determine the current JRE version via java.lang.Runtime.Version."); } - // null signals that the current JRE version is "unknown" - return null; + return UNDEFINED_VERSION; + } + + private static JRE determineCurrentJre(int currentVersion) { + switch (currentVersion) { + case UNDEFINED_VERSION: + // null signals that the current JRE version is undefined. + return null;<%-- + --%>@for(var jre : jres) + case ${jre.getVersion()}: + return JAVA_${jre.getVersion()};<%-- + --%>@endfor + default: + return OTHER; + } + } + + private final int version; + + private JRE(int version) { + this.version = version; + } + + /** + * Get the version of this {@code JRE}. + * + *

If this {@code JRE} is {@link #UNDEFINED}, this method returns + * {@code -1}. If this {@code JRE} is {@link #OTHER}, this method returns + * {@link Integer#MAX_VALUE}. + * + * @return the version of this {@code JRE} + * @since 5.12 + * @see Runtime.Version#feature() + * @see #currentVersionNumber() + */ + @API(status = EXPERIMENTAL, since = "5.12") + public int version() { + return this.version; } /** * @return {@code true} if this {@code JRE} is known to be the * Java Runtime Environment version for the currently executing JVM or if * the version is {@link #OTHER} + * + * @see #currentJre() + * @see #currentVersionNumber() */ public boolean isCurrentVersion() { - return this == CURRENT_VERSION; + return this == CURRENT_JRE; } /** @@ -121,14 +171,56 @@ public enum JRE { * {@link #OTHER} * * @since 5.7 + * @see #currentVersionNumber() + * @deprecated in favor of {@link #currentJre()} */ - @API(status = STABLE, since = "5.7") + @API(status = DEPRECATED, since = "5.12") + @Deprecated public static JRE currentVersion() { + return currentJre(); + } + + /** + * @return the {@link JRE} for the currently executing JVM, potentially + * {@link #OTHER} + * + * @since 5.12 + * @see #currentVersionNumber() + */ + @API(status = EXPERIMENTAL, since = "5.12") + public static JRE currentJre() { + return CURRENT_JRE; + } + + /** + * @return the version number for the currently executing JVM, or {@code -1} + * to signal that the version is undefined + * + * @since 5.12 + * @see Runtime.Version#feature() + * @see #currentJre() + */ + @API(status = EXPERIMENTAL, since = "5.12") + public static int currentVersionNumber() { return CURRENT_VERSION; } - static boolean isCurrentVersionWithinRange(JRE min, JRE max) { - return EnumSet.range(min, max).contains(CURRENT_VERSION); + /** + * @return {@code true} if the supplied version number is known to be the + * Java Runtime Environment version for the currently executing JVM or if + * the supplied version number is {@code -1} and the version of the current + * JVM is unknown + * + * @since 5.12 + * @see Runtime.Version#feature() + */ + @API(status = EXPERIMENTAL, since = "5.12") + public static boolean isCurrentVersion(int version) { + return version == CURRENT_VERSION; + } + + static boolean isCurrentVersionWithinRange(int min, int max) { + return CURRENT_VERSION >= min && CURRENT_VERSION <= max; } } diff --git a/jupiter-tests/src/templates/resources/test/org/junit/jupiter/api/condition/DisabledOnJreConditionTests.java.jte b/jupiter-tests/src/templates/resources/test/org/junit/jupiter/api/condition/DisabledOnJreConditionTests.java.jte index fc4d8884be75..ae3491d85317 100644 --- a/jupiter-tests/src/templates/resources/test/org/junit/jupiter/api/condition/DisabledOnJreConditionTests.java.jte +++ b/jupiter-tests/src/templates/resources/test/org/junit/jupiter/api/condition/DisabledOnJreConditionTests.java.jte @@ -19,7 +19,8 @@ import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.platform.commons.PreconditionViolationException; /** - * Unit tests for {@link DisabledOnJreCondition}. + * Unit tests for {@link DisabledOnJreCondition}, generated from + * {@code DisabledOnJreConditionTests.java.jte}. * *

Note that test method names MUST match the test method names in * {@link DisabledOnJreIntegrationTests}. @@ -28,6 +29,8 @@ import org.junit.platform.commons.PreconditionViolationException; */ class DisabledOnJreConditionTests extends AbstractExecutionConditionTests { + private static final String JAVA_VERSION = System.getProperty("java.version"); + @Override protected ExecutionCondition getExecutionCondition() { return new DisabledOnJreCondition(); @@ -49,12 +52,12 @@ class DisabledOnJreConditionTests extends AbstractExecutionConditionTests { } /** - * @see DisabledOnJreIntegrationTests#missingJreDeclaration() + * @see DisabledOnJreIntegrationTests#missingVersionDeclaration() */ @Test - void missingJreDeclaration() { + void missingVersionDeclaration() { Exception exception = assertThrows(PreconditionViolationException.class, this::evaluateCondition); - assertThat(exception).hasMessageContaining("You must declare at least one JRE"); + assertThat(exception).hasMessage("You must declare at least one JRE or version in @DisabledOnJre"); } /** @@ -68,10 +71,20 @@ class DisabledOnJreConditionTests extends AbstractExecutionConditionTests { } @for(var jre : jres) /** - * @see DisabledOnJreIntegrationTests#java${jre.getVersion()}() + * @see DisabledOnJreIntegrationTests#jre${jre.getVersion()}() + */ + @Test + void jre${jre.getVersion()}() { + evaluateCondition(); + assertDisabledOnCurrentJreIf(onJava${jre.getVersion()}()); + } +@endfor<%-- +--%>@for(var jre : jres) + /** + * @see DisabledOnJreIntegrationTests#version${jre.getVersion()}() */ @Test - void java${jre.getVersion()}() { + void version${jre.getVersion()}() { evaluateCondition(); assertDisabledOnCurrentJreIf(onJava${jre.getVersion()}()); } @@ -88,11 +101,11 @@ class DisabledOnJreConditionTests extends AbstractExecutionConditionTests { private void assertDisabledOnCurrentJreIf(boolean condition) { if (condition) { assertDisabled(); - assertReasonContains("Disabled on JRE version: " + System.getProperty("java.version")); + assertReasonContains("Disabled on JRE version: " + JAVA_VERSION); } else { assertEnabled(); - assertReasonContains("Enabled on JRE version: " + System.getProperty("java.version")); + assertReasonContains("Enabled on JRE version: " + JAVA_VERSION); } } diff --git a/jupiter-tests/src/templates/resources/test/org/junit/jupiter/api/condition/DisabledOnJreIntegrationTests.java.jte b/jupiter-tests/src/templates/resources/test/org/junit/jupiter/api/condition/DisabledOnJreIntegrationTests.java.jte index 6d86cd5c670b..1b5c747615c4 100644 --- a/jupiter-tests/src/templates/resources/test/org/junit/jupiter/api/condition/DisabledOnJreIntegrationTests.java.jte +++ b/jupiter-tests/src/templates/resources/test/org/junit/jupiter/api/condition/DisabledOnJreIntegrationTests.java.jte @@ -23,7 +23,8 @@ import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; /** - * Integration tests for {@link DisabledOnJre}. + * Integration tests for {@link DisabledOnJre @DisabledOnJre}, generated from + * {@code DisabledOnJreIntegrationTests.java.jte}. * * @since 5.1 */ @@ -37,7 +38,7 @@ class DisabledOnJreIntegrationTests { @Test @Disabled("Only used in a unit test via reflection") @DisabledOnJre({}) - void missingJreDeclaration() { + void missingVersionDeclaration() { } @Test @@ -53,7 +54,14 @@ class DisabledOnJreIntegrationTests { @for(var jre : jres) @Test @DisabledOnJre(JAVA_${jre.getVersion()}) - void java${jre.getVersion()}() { + void jre${jre.getVersion()}() { + assertFalse(onJava${jre.getVersion()}()); + } +@endfor<%-- +--%>@for(var jre : jres) + @Test + @DisabledOnJre(versions = ${jre.getVersion()}) + void version${jre.getVersion()}() { assertFalse(onJava${jre.getVersion()}()); } @endfor diff --git a/jupiter-tests/src/templates/resources/test/org/junit/jupiter/api/condition/EnabledOnJreConditionTests.java.jte b/jupiter-tests/src/templates/resources/test/org/junit/jupiter/api/condition/EnabledOnJreConditionTests.java.jte index 81c9e1cc4dfd..6e1d2e372cb2 100644 --- a/jupiter-tests/src/templates/resources/test/org/junit/jupiter/api/condition/EnabledOnJreConditionTests.java.jte +++ b/jupiter-tests/src/templates/resources/test/org/junit/jupiter/api/condition/EnabledOnJreConditionTests.java.jte @@ -19,7 +19,8 @@ import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.platform.commons.PreconditionViolationException; /** - * Unit tests for {@link EnabledOnJreCondition}. + * Unit tests for {@link EnabledOnJreCondition}, generated from + * {@code EnabledOnJreConditionTests.java.jte}. * *

Note that test method names MUST match the test method names in * {@link EnabledOnJreIntegrationTests}. @@ -28,6 +29,8 @@ import org.junit.platform.commons.PreconditionViolationException; */ class EnabledOnJreConditionTests extends AbstractExecutionConditionTests { + private static final String JAVA_VERSION = System.getProperty("java.version"); + @Override protected ExecutionCondition getExecutionCondition() { return new EnabledOnJreCondition(); @@ -49,12 +52,12 @@ class EnabledOnJreConditionTests extends AbstractExecutionConditionTests { } /** - * @see EnabledOnJreIntegrationTests#missingJreDeclaration() + * @see EnabledOnJreIntegrationTests#missingVersionDeclaration() */ @Test - void missingJreDeclaration() { + void missingVersionDeclaration() { Exception exception = assertThrows(PreconditionViolationException.class, this::evaluateCondition); - assertThat(exception).hasMessageContaining("You must declare at least one JRE"); + assertThat(exception).hasMessage("You must declare at least one JRE or version in @EnabledOnJre"); } /** @@ -67,10 +70,20 @@ class EnabledOnJreConditionTests extends AbstractExecutionConditionTests { } @for(var jre : jres) /** - * @see EnabledOnJreIntegrationTests#java${jre.getVersion()}() + * @see EnabledOnJreIntegrationTests#jre${jre.getVersion()}() + */ + @Test + void jre${jre.getVersion()}() { + evaluateCondition(); + assertEnabledOnCurrentJreIf(onJava${jre.getVersion()}()); + } +@endfor<%-- +--%>@for(var jre : jres) + /** + * @see EnabledOnJreIntegrationTests#version${jre.getVersion()}() */ @Test - void java${jre.getVersion()}() { + void version${jre.getVersion()}() { evaluateCondition(); assertEnabledOnCurrentJreIf(onJava${jre.getVersion()}()); } @@ -88,11 +101,11 @@ class EnabledOnJreConditionTests extends AbstractExecutionConditionTests { private void assertEnabledOnCurrentJreIf(boolean condition) { if (condition) { assertEnabled(); - assertReasonContains("Enabled on JRE version: " + System.getProperty("java.version")); + assertReasonContains("Enabled on JRE version: " + JAVA_VERSION); } else { assertDisabled(); - assertReasonContains("Disabled on JRE version: " + System.getProperty("java.version")); + assertReasonContains("Disabled on JRE version: " + JAVA_VERSION); } } diff --git a/jupiter-tests/src/templates/resources/test/org/junit/jupiter/api/condition/EnabledOnJreIntegrationTests.java.jte b/jupiter-tests/src/templates/resources/test/org/junit/jupiter/api/condition/EnabledOnJreIntegrationTests.java.jte index 7aee1f374c73..22a828f028e0 100644 --- a/jupiter-tests/src/templates/resources/test/org/junit/jupiter/api/condition/EnabledOnJreIntegrationTests.java.jte +++ b/jupiter-tests/src/templates/resources/test/org/junit/jupiter/api/condition/EnabledOnJreIntegrationTests.java.jte @@ -22,7 +22,8 @@ import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; /** - * Integration tests for {@link EnabledOnJre}. + * Integration tests for {@link EnabledOnJre @EnabledOnJre}, generated from + * {@code EnabledOnJreIntegrationTests.java.jte}. * * @since 5.1 */ @@ -36,7 +37,7 @@ class EnabledOnJreIntegrationTests { @Test @Disabled("Only used in a unit test via reflection") @EnabledOnJre({}) - void missingJreDeclaration() { + void missingVersionDeclaration() { } @Test @@ -51,7 +52,14 @@ class EnabledOnJreIntegrationTests { @for(var jre : jres) @Test @EnabledOnJre(JAVA_${jre.getVersion()}) - void java${jre.getVersion()}() { + void jre${jre.getVersion()}() { + assertTrue(onJava${jre.getVersion()}()); + } +@endfor<%-- +--%>@for(var jre : jres) + @Test + @EnabledOnJre(versions = ${jre.getVersion()}) + void version${jre.getVersion()}() { assertTrue(onJava${jre.getVersion()}()); } @endfor diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/AbstractExecutionConditionTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/AbstractExecutionConditionTests.java index 2dceb1d3f2a8..bff8050468de 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/AbstractExecutionConditionTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/AbstractExecutionConditionTests.java @@ -65,7 +65,7 @@ void ensureAllTestMethodsAreCovered() { List localTestMethods = findMethods(getClass(), isTestMethod, TOP_DOWN).stream()// .map(Method::getName).sorted().toList(); - assertThat(localTestMethods).isEqualTo(methodsToTest); + assertThat(localTestMethods).containsExactlyElementsOf(methodsToTest); } @BeforeEach diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/DisabledForJreRangeConditionTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/DisabledForJreRangeConditionTests.java index cfcd7fcdd9b5..50b84363d5d0 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/DisabledForJreRangeConditionTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/DisabledForJreRangeConditionTests.java @@ -39,6 +39,8 @@ */ class DisabledForJreRangeConditionTests extends AbstractExecutionConditionTests { + private static final String JAVA_VERSION = System.getProperty("java.version"); + @Override protected ExecutionCondition getExecutionCondition() { return new DisabledForJreRangeCondition(); @@ -66,7 +68,8 @@ void enabledBecauseAnnotationIsNotPresent() { void defaultValues() { assertThatExceptionOfType(PreconditionViolationException.class)// .isThrownBy(this::evaluateCondition)// - .withMessageContaining("You must declare a non-default value for min or max in @DisabledForJreRange"); + .withMessageContaining( + "You must declare a non-default value for the minimum or maximum value in @DisabledForJreRange"); } /** @@ -119,11 +122,11 @@ void other() { private void assertDisabledOnCurrentJreIf(boolean condition) { if (condition) { assertDisabled(); - assertReasonContains("Disabled on JRE version: " + System.getProperty("java.version")); + assertReasonContains("Disabled on JRE version: " + JAVA_VERSION); } else { assertEnabled(); - assertReasonContains("Enabled on JRE version: " + System.getProperty("java.version")); + assertReasonContains("Enabled on JRE version: " + JAVA_VERSION); } } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/EnabledForJreRangeConditionTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/EnabledForJreRangeConditionTests.java index 4bb80e722c6d..4a800cb150ee 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/EnabledForJreRangeConditionTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/EnabledForJreRangeConditionTests.java @@ -21,6 +21,8 @@ import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava17; import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava18; import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava19; +import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava20; +import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava21; import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava8; import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava9; import static org.junit.jupiter.api.condition.JavaVersionPredicates.onKnownVersion; @@ -30,7 +32,7 @@ import org.junit.platform.commons.PreconditionViolationException; /** - * Unit tests for {@link EnabledForJreRange}. + * Unit tests for {@link EnabledForJreRange @EnabledForJreRange}. * *

Note that test method names MUST match the test method names in * {@link EnabledForJreRangeIntegrationTests}. @@ -39,6 +41,8 @@ */ class EnabledForJreRangeConditionTests extends AbstractExecutionConditionTests { + private static final String JAVA_VERSION = System.getProperty("java.version"); + @Override protected ExecutionCondition getExecutionCondition() { return new EnabledForJreRangeCondition(); @@ -66,63 +70,238 @@ void enabledBecauseAnnotationIsNotPresent() { void defaultValues() { assertThatExceptionOfType(PreconditionViolationException.class)// .isThrownBy(this::evaluateCondition)// - .withMessageContaining("You must declare a non-default value for min or max in @EnabledForJreRange"); + .withMessageContaining( + "You must declare a non-default value for the minimum or maximum value in @EnabledForJreRange"); + } + + /** + * @see EnabledForJreRangeIntegrationTests#minVersion7() + */ + @Test + void minVersion7() { + assertThatExceptionOfType(PreconditionViolationException.class)// + .isThrownBy(this::evaluateCondition)// + .withMessage("@EnabledForJreRange's minVersion [7] must be greater than or equal to 8"); + } + + /** + * @see EnabledForJreRangeIntegrationTests#maxVersion7() + */ + @Test + void maxVersion7() { + assertThatExceptionOfType(PreconditionViolationException.class)// + .isThrownBy(this::evaluateCondition)// + .withMessage("@EnabledForJreRange's maxVersion [7] must be greater than or equal to 8"); + } + + /** + * @see EnabledForJreRangeIntegrationTests#minAndMinVersion() + */ + @Test + void minAndMinVersion() { + assertThatExceptionOfType(PreconditionViolationException.class)// + .isThrownBy(this::evaluateCondition)// + .withMessage( + "@EnabledForJreRange's minimum value must be configured with either a JRE enum constant or numeric version, but not both"); + } + + /** + * @see EnabledForJreRangeIntegrationTests#maxAndMaxVersion() + */ + @Test + void maxAndMaxVersion() { + assertThatExceptionOfType(PreconditionViolationException.class)// + .isThrownBy(this::evaluateCondition)// + .withMessage( + "@EnabledForJreRange's maximum value must be configured with either a JRE enum constant or numeric version, but not both"); } /** - * @see EnabledForJreRangeIntegrationTests#java17() + * @see EnabledForJreRangeIntegrationTests#minGreaterThanMax() */ @Test - void java17() { + void minGreaterThanMax() { + assertThatExceptionOfType(PreconditionViolationException.class)// + .isThrownBy(this::evaluateCondition)// + .withMessage( + "@EnabledForJreRange's minimum value [21] must be less than or equal to its maximum value [11]"); + } + + /** + * @see EnabledForJreRangeIntegrationTests#minGreaterThanMaxVersion() + */ + @Test + void minGreaterThanMaxVersion() { + minGreaterThanMax(); + } + + /** + * @see EnabledForJreRangeIntegrationTests#minVersionGreaterThanMaxVersion() + */ + @Test + void minVersionGreaterThanMaxVersion() { + minGreaterThanMax(); + } + + /** + * @see EnabledForJreRangeIntegrationTests#minVersionGreaterThanMax() + */ + @Test + void minVersionGreaterThanMax() { + minGreaterThanMax(); + } + + /** + * @see EnabledForJreRangeIntegrationTests#min8() + */ + @Test + void min8() { evaluateCondition(); - assertEnabledOnCurrentJreIf(onJava17()); + // Nothing to assert: the test should always be enabled. + } + + /** + * @see EnabledForJreRangeIntegrationTests#minVersion8() + */ + @Test + void minVersion8() { + min8(); } /** - * @see EnabledForJreRangeIntegrationTests#java18to19() + * @see EnabledForJreRangeIntegrationTests#min20() */ @Test - void java18to19() { + void min20() { evaluateCondition(); - assertEnabledOnCurrentJreIf(onJava18() || onJava19()); + assertEnabledOnCurrentJreIf(!(onJava19())); } /** - * @see EnabledForJreRangeIntegrationTests#javaMax18() + * @see EnabledForJreRangeIntegrationTests#minVersion20() */ @Test - void javaMax18() { + void minVersion20() { + min20(); + } + + /** + * @see EnabledForJreRangeIntegrationTests#max21() + */ + @Test + void max21() { evaluateCondition(); - assertEnabledOnCurrentJreIf(onJava8() || onJava9() || onJava10() || onJava11() || onJava12() || onJava13() - || onJava14() || onJava15() || onJava16() || onJava17() || onJava18()); + assertEnabledOnCurrentJreIf( + onJava8() || onJava9() || onJava10() || onJava11() || onJava12() || onJava13() || onJava14() || onJava15() + || onJava16() || onJava17() || onJava18() || onJava19() || onJava20() || onJava21()); } /** - * @see EnabledForJreRangeIntegrationTests#javaMin18() + * @see EnabledForJreRangeIntegrationTests#maxVersion21() */ @Test - void javaMin18() { + void maxVersion21() { + max21(); + } + + /** + * @see EnabledForJreRangeIntegrationTests#min17Max17() + */ + @Test + void min17Max17() { evaluateCondition(); - assertEnabledOnCurrentJreIf(!(onJava17())); + assertEnabledOnCurrentJreIf(onJava17()); } /** - * @see EnabledForJreRangeIntegrationTests#other() + * @see EnabledForJreRangeIntegrationTests#min17MaxVersion17() */ @Test - void other() { + void min17MaxVersion17() { + min17Max17(); + } + + /** + * @see EnabledForJreRangeIntegrationTests#minVersion17Max17() + */ + @Test + void minVersion17Max17() { + min17Max17(); + } + + /** + * @see EnabledForJreRangeIntegrationTests#minVersion17MaxVersion17() + */ + @Test + void minVersion17MaxVersion17() { + min17Max17(); + } + + /** + * @see EnabledForJreRangeIntegrationTests#min20Max21() + */ + @Test + void min20Max21() { + evaluateCondition(); + assertEnabledOnCurrentJreIf(onJava20() || onJava21()); + } + + /** + * @see EnabledForJreRangeIntegrationTests#min20MaxVersion21() + */ + @Test + void min20MaxVersion21() { + min20Max21(); + } + + /** + * @see EnabledForJreRangeIntegrationTests#minVersion20Max21() + */ + @Test + void minVersion20Max21() { + min20Max21(); + } + + /** + * @see EnabledForJreRangeIntegrationTests#minVersion20MaxVersion21() + */ + @Test + void minVersion20MaxVersion21() { + min20Max21(); + } + + /** + * @see EnabledForJreRangeIntegrationTests#minOtherMaxOther() + */ + @Test + void minOtherMaxOther() { evaluateCondition(); assertEnabledOnCurrentJreIf(!onKnownVersion()); } + /** + * @see EnabledForJreRangeIntegrationTests#minMaxIntegerMaxMaxInteger() + */ + @Test + void minMaxIntegerMaxMaxInteger() { + minOtherMaxOther(); + } + + /** + * @see EnabledForJreRangeIntegrationTests#maxVersionMaxInteger() + */ + @Test + void maxVersionMaxInteger() { + } + private void assertEnabledOnCurrentJreIf(boolean condition) { if (condition) { assertEnabled(); - assertReasonContains("Enabled on JRE version: " + System.getProperty("java.version")); + assertReasonContains("Enabled on JRE version: " + JAVA_VERSION); } else { assertDisabled(); - assertReasonContains("Disabled on JRE version: " + System.getProperty("java.version")); + assertReasonContains("Disabled on JRE version: " + JAVA_VERSION); } } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/EnabledForJreRangeIntegrationTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/EnabledForJreRangeIntegrationTests.java index 8ce5f2bc4329..0fda16467fb4 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/EnabledForJreRangeIntegrationTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/EnabledForJreRangeIntegrationTests.java @@ -13,9 +13,12 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; +import static org.junit.jupiter.api.condition.JRE.JAVA_11; import static org.junit.jupiter.api.condition.JRE.JAVA_17; import static org.junit.jupiter.api.condition.JRE.JAVA_18; -import static org.junit.jupiter.api.condition.JRE.JAVA_19; +import static org.junit.jupiter.api.condition.JRE.JAVA_20; +import static org.junit.jupiter.api.condition.JRE.JAVA_21; +import static org.junit.jupiter.api.condition.JRE.JAVA_8; import static org.junit.jupiter.api.condition.JRE.OTHER; import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava10; import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava11; @@ -27,6 +30,10 @@ import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava17; import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava18; import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava19; +import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava20; +import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava21; +import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava22; +import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava23; import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava8; import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava9; import static org.junit.jupiter.api.condition.JavaVersionPredicates.onKnownVersion; @@ -35,12 +42,14 @@ import org.junit.jupiter.api.Test; /** - * Integration tests for {@link EnabledForJreRange}. + * Integration tests for {@link EnabledForJreRange @EnabledForJreRange}. * * @since 5.6 */ class EnabledForJreRangeIntegrationTests { + private static final JRE CURRENT_JRE = JRE.currentJre(); + @Test @Disabled("Only used in a unit test via reflection") void enabledBecauseAnnotationIsNotPresent() { @@ -54,38 +63,190 @@ void defaultValues() { } @Test - @EnabledForJreRange(min = JAVA_17, max = JAVA_17) - void java17() { - assertTrue(onJava17()); + @Disabled("Only used in a unit test via reflection") + @EnabledForJreRange(minVersion = 7) + void minVersion7() { + fail("should result in a configuration exception"); } @Test - @EnabledForJreRange(min = JAVA_18, max = JAVA_19) - void java18to19() { - assertTrue(onJava18() || onJava19()); - assertFalse(onJava17()); + @Disabled("Only used in a unit test via reflection") + @EnabledForJreRange(maxVersion = 7) + void maxVersion7() { + fail("should result in a configuration exception"); } @Test - @EnabledForJreRange(max = JAVA_18) - void javaMax18() { - assertTrue(onJava8() || onJava9() || onJava10() || onJava11() || onJava12() || onJava13() || onJava14() - || onJava15() || onJava16() || onJava17() || onJava18()); + @Disabled("Only used in a unit test via reflection") + @EnabledForJreRange(min = JAVA_18, minVersion = 21) + void minAndMinVersion() { + fail("should result in a configuration exception"); + } + + @Test + @Disabled("Only used in a unit test via reflection") + @EnabledForJreRange(max = JAVA_18, maxVersion = 21) + void maxAndMaxVersion() { + fail("should result in a configuration exception"); + } + + @Test + @Disabled("Only used in a unit test via reflection") + @EnabledForJreRange(min = JAVA_21, max = JAVA_11) + void minGreaterThanMax() { + fail("should result in a configuration exception"); + } + + @Test + @Disabled("Only used in a unit test via reflection") + @EnabledForJreRange(min = JAVA_21, maxVersion = 11) + void minGreaterThanMaxVersion() { + fail("should result in a configuration exception"); + } + + @Test + @Disabled("Only used in a unit test via reflection") + @EnabledForJreRange(minVersion = 21, maxVersion = 11) + void minVersionGreaterThanMaxVersion() { + fail("should result in a configuration exception"); + } + + @Test + @Disabled("Only used in a unit test via reflection") + @EnabledForJreRange(minVersion = 21, max = JAVA_11) + void minVersionGreaterThanMax() { + fail("should result in a configuration exception"); + } + + /** + * We need this in addition to {@link #min20()} to verify that the lowest + * JRE version is supported as a boundary. + */ + @Test + @EnabledForJreRange(min = JAVA_8) + void min8() { + assertTrue(onKnownVersion()); + assertTrue(JRE.currentVersionNumber() >= 8); + assertTrue(CURRENT_JRE.compareTo(JAVA_8) >= 0); + assertTrue(CURRENT_JRE.version() >= 8); + } + + /** + * We need this in addition to {@link #minVersion20()} to verify that the lowest + * JRE version is supported as a boundary. + */ + @Test + @EnabledForJreRange(minVersion = 8) + void minVersion8() { + min8(); + } + + @Test + @EnabledForJreRange(min = JAVA_20) + void min20() { + assertTrue(onKnownVersion()); + assertTrue(JRE.currentVersionNumber() >= 20); + assertTrue(CURRENT_JRE.compareTo(JAVA_20) >= 0); + assertTrue(CURRENT_JRE.version() >= 20); assertFalse(onJava19()); } @Test - @EnabledForJreRange(min = JAVA_18) - void javaMin18() { + @EnabledForJreRange(minVersion = 20) + void minVersion20() { + min20(); + } + + @Test + @EnabledForJreRange(max = JAVA_21) + void max21() { assertTrue(onKnownVersion()); - assertTrue(JRE.currentVersion().compareTo(JAVA_18) >= 0); - assertFalse(onJava17()); + assertTrue(JRE.currentVersionNumber() <= 21); + assertTrue(CURRENT_JRE.compareTo(JAVA_21) <= 0); + assertTrue(CURRENT_JRE.version() <= 21); + + assertTrue(onJava8() || onJava9() || onJava10() || onJava11() || onJava12() || onJava13() || onJava14() + || onJava15() || onJava16() || onJava17() || onJava18() || onJava19() || onJava20() || onJava21()); + assertFalse(onJava22()); + } + + @Test + @EnabledForJreRange(maxVersion = 21) + void maxVersion21() { + max21(); + } + + @Test + @EnabledForJreRange(min = JAVA_17, max = JAVA_17) + void min17Max17() { + assertTrue(onJava17()); + } + + @Test + @EnabledForJreRange(min = JAVA_17, maxVersion = 17) + void min17MaxVersion17() { + min17Max17(); + } + + @Test + @EnabledForJreRange(minVersion = 17, max = JAVA_17) + void minVersion17Max17() { + min17Max17(); + } + + @Test + @EnabledForJreRange(minVersion = 17, maxVersion = 17) + void minVersion17MaxVersion17() { + min17Max17(); + } + + @Test + @EnabledForJreRange(min = JAVA_20, max = JAVA_21) + void min20Max21() { + assertTrue(onJava20() || onJava21()); + assertFalse(onJava17() || onJava23()); + } + + @Test + @EnabledForJreRange(min = JAVA_20, maxVersion = 21) + void min20MaxVersion21() { + min20Max21(); + } + + @Test + @EnabledForJreRange(minVersion = 20, max = JAVA_21) + void minVersion20Max21() { + min20Max21(); + } + + @Test + @EnabledForJreRange(minVersion = 20, maxVersion = 21) + void minVersion20MaxVersion21() { + min20Max21(); } @Test @EnabledForJreRange(min = OTHER, max = OTHER) - void other() { + void minOtherMaxOther() { assertFalse(onKnownVersion()); } + @Test + @EnabledForJreRange(minVersion = Integer.MAX_VALUE, maxVersion = Integer.MAX_VALUE) + void minMaxIntegerMaxMaxInteger() { + minOtherMaxOther(); + } + + /** + * We need this in addition to {@link #maxVersion21()} to verify that + * {@link Integer#MAX_VALUE} is supported as an upper bound. + */ + @Test + @EnabledForJreRange(maxVersion = Integer.MAX_VALUE) + void maxVersionMaxInteger() { + assertTrue(onKnownVersion()); + assertTrue(JRE.currentVersionNumber() >= 8); + assertTrue(JRE.currentVersionNumber() <= Integer.MAX_VALUE); + } + } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/JRETests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/JRETests.java index 548df968e8cc..6e96da89f82d 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/JRETests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/JRETests.java @@ -10,13 +10,15 @@ package org.junit.jupiter.api.condition; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.condition.JRE.JAVA_17; import static org.junit.jupiter.api.condition.JRE.JAVA_18; import static org.junit.jupiter.api.condition.JRE.JAVA_19; import static org.junit.jupiter.api.condition.JRE.JAVA_20; import static org.junit.jupiter.api.condition.JRE.JAVA_21; import static org.junit.jupiter.api.condition.JRE.JAVA_22; +import static org.junit.jupiter.api.condition.JRE.JAVA_23; +import static org.junit.jupiter.api.condition.JRE.JAVA_24; import static org.junit.jupiter.api.condition.JRE.OTHER; import org.junit.jupiter.api.Test; @@ -28,45 +30,123 @@ */ public class JRETests { + private static final JRE CURRENT_JRE = JRE.currentJre(); + @Test @EnabledOnJre(JAVA_17) - void java17() { - assertEquals(JAVA_17, JRE.currentVersion()); + void jre17() { + assertThat(CURRENT_JRE).as("current version").isEqualTo(JAVA_17); + assertThat(CURRENT_JRE.version()).as("current feature version").isEqualTo(17); } @Test @EnabledOnJre(JAVA_18) - void java18() { - assertEquals(JAVA_18, JRE.currentVersion()); + void jre18() { + assertThat(CURRENT_JRE).as("current version").isEqualTo(JAVA_18); + assertThat(CURRENT_JRE.version()).as("current feature version").isEqualTo(18); } @Test @EnabledOnJre(JAVA_19) - void java19() { - assertEquals(JAVA_19, JRE.currentVersion()); + void jre19() { + assertThat(CURRENT_JRE).as("current version").isEqualTo(JAVA_19); + assertThat(CURRENT_JRE.version()).as("current feature version").isEqualTo(19); } @Test @EnabledOnJre(JAVA_20) - void java20() { - assertEquals(JAVA_20, JRE.currentVersion()); + void jre20() { + assertThat(CURRENT_JRE).as("current version").isEqualTo(JAVA_20); + assertThat(CURRENT_JRE.version()).as("current feature version").isEqualTo(20); } @Test @EnabledOnJre(JAVA_21) - void java21() { - assertEquals(JAVA_21, JRE.currentVersion()); + void jre21() { + assertThat(CURRENT_JRE).as("current version").isEqualTo(JAVA_21); + assertThat(CURRENT_JRE.version()).as("current feature version").isEqualTo(21); } @Test @EnabledOnJre(JAVA_22) - void java22() { - assertEquals(JAVA_22, JRE.currentVersion()); + void jre22() { + assertThat(CURRENT_JRE).as("current version").isEqualTo(JAVA_21); + assertThat(CURRENT_JRE.version()).as("current feature version").isEqualTo(22); + } + + @Test + @EnabledOnJre(JAVA_23) + void jre23() { + assertThat(CURRENT_JRE).as("current version").isEqualTo(JAVA_23); + assertThat(CURRENT_JRE.version()).as("current feature version").isEqualTo(23); + } + + @Test + @EnabledOnJre(JAVA_24) + void jre24() { + assertThat(CURRENT_JRE).as("current version").isEqualTo(JAVA_24); + assertThat(CURRENT_JRE.version()).as("current feature version").isEqualTo(24); + } + + @Test + @EnabledOnJre(versions = 17) + void version17() { + jre17(); + } + + @Test + @EnabledOnJre(versions = 18) + void version18() { + jre18(); + } + + @Test + @EnabledOnJre(versions = 19) + void version19() { + jre19(); + } + + @Test + @EnabledOnJre(versions = 20) + void version20() { + jre20(); + } + + @Test + @EnabledOnJre(versions = 21) + void version21() { + jre21(); + } + + @Test + @EnabledOnJre(versions = 22) + void version22() { + jre22(); + } + + @Test + @EnabledOnJre(versions = 23) + void version23() { + jre23(); + } + + @Test + @EnabledOnJre(versions = 24) + void version24() { + jre24(); } @Test @EnabledOnJre(OTHER) - void other() { - assertEquals(OTHER, JRE.currentVersion()); + void jreOther() { + assertThat(CURRENT_JRE).as("current version").isEqualTo(OTHER); + assertThat(CURRENT_JRE.version()).as("current feature version").isEqualTo(Integer.MAX_VALUE); } + + @Test + @EnabledOnJre(versions = Integer.MAX_VALUE) + void versionMaxInteger() { + jreOther(); + } + } diff --git a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/JavaVersionsTests.java b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/JavaVersionsTests.java index 417bb8119906..5c35fa41b844 100644 --- a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/JavaVersionsTests.java +++ b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/JavaVersionsTests.java @@ -51,7 +51,7 @@ void java_8(@FilePrefix("maven") OutputFiles outputFiles) throws Exception { @Test void java_default(@FilePrefix("maven") OutputFiles outputFiles) throws Exception { - var actualLines = execute(currentJdkHome(), outputFiles, MavenEnvVars.forJre(JRE.currentVersion())); + var actualLines = execute(currentJdkHome(), outputFiles, MavenEnvVars.forJre(JRE.currentJre())); assertTrue(actualLines.contains("[WARNING] Tests run: 2, Failures: 0, Errors: 0, Skipped: 1")); } diff --git a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/MultiReleaseJarTests.java b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/MultiReleaseJarTests.java index 4326fa6fa7c9..035a4d5fcdae 100644 --- a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/MultiReleaseJarTests.java +++ b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/MultiReleaseJarTests.java @@ -77,7 +77,7 @@ void checkDefault(@TempDir Path workspace, @FilePrefix("maven") OutputFiles outp .addArguments("-Dsnapshot.repo.url=" + mavenRepoProxy.getBaseUri()) // .addArguments("--update-snapshots", "--show-version", "--errors", "--batch-mode") // .addArguments("test") // - .putEnvironment(MavenEnvVars.forJre(JRE.currentVersion())) // + .putEnvironment(MavenEnvVars.forJre(JRE.currentJre())) // .redirectOutput(outputFiles) // .startAndWait(); diff --git a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/UnalignedClasspathTests.java b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/UnalignedClasspathTests.java index 7869a3d59186..62ca57d144f2 100644 --- a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/UnalignedClasspathTests.java +++ b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/UnalignedClasspathTests.java @@ -69,7 +69,7 @@ void verifyErrorMessageForUnalignedClasspath(JRE jre, Path javaHome, @TempDir Pa static Stream javaVersions() { return Stream.concat( // Helper.getJavaHome("8").map(path -> Arguments.of(JRE.JAVA_8, path)).stream(), // - Stream.of(Arguments.of(JRE.currentVersion(), currentJdkHome())) // + Stream.of(Arguments.of(JRE.currentJre(), currentJdkHome())) // ); } }