diff --git a/README.md b/README.md index 724b832714de..b6b930b1a4d8 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ This repository is the home of _JUnit 5_. ## Latest Releases -- General Availability (GA): [JUnit 5.13.2](https://github.com/junit-team/junit-framework/releases/tag/r5.13.2) (June 24, 2025) +- General Availability (GA): [JUnit 5.13.3](https://github.com/junit-team/junit-framework/releases/tag/r5.13.3) (July 4, 2025) - Preview (Milestone/Release Candidate): [JUnit 5.13.0-RC1](https://github.com/junit-team/junit-framework/releases/tag/r5.13.0-RC1) (May 16, 2025) ## Documentation diff --git a/documentation/src/docs/asciidoc/release-notes/index.adoc b/documentation/src/docs/asciidoc/release-notes/index.adoc index 6bb9b4c46d3d..8bc95ee43e4f 100644 --- a/documentation/src/docs/asciidoc/release-notes/index.adoc +++ b/documentation/src/docs/asciidoc/release-notes/index.adoc @@ -17,6 +17,8 @@ authors as well as build tool and IDE vendors. include::{includedir}/link-attributes.adoc[] +include::{basedir}/release-notes-5.13.3.adoc[] + include::{basedir}/release-notes-5.13.2.adoc[] include::{basedir}/release-notes-5.13.1.adoc[] diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.2.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.2.adoc index ae95787331ba..92d774120e0b 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.2.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.2.adoc @@ -3,7 +3,7 @@ *Date of Release:* June 24, 2025 -*Scope:* Bug fixes and enhancements since 5.13.0 +*Scope:* Bug fixes and enhancements since 5.13.1 For a complete list of all _closed_ issues and pull requests for this release, consult the link:{junit-framework-repo}+/milestone/98?closed=1+[5.13.2] milestone page in the JUnit @@ -13,6 +13,19 @@ repository on GitHub. [[release-notes-5.13.2-junit-platform]] === JUnit Platform +[[release-notes-5.13.2-junit-platform-bug-fixes]] +==== Bug Fixes + +* If Git information is included in the Open Test Reporting XML format (see below), any + credentials that may be configured as part the `remote.origin.url` setting in Git were + previously written to the `originUrl` attribute of `` elements. For + example, when cloning a GitHub repository using a URL like + `https://username:password@github.com/organization/repository.git`, both username and + password were included in the XML report. Since a report which includes this information + may be shared, published, or archived (for example, on a CI server), this was reported + as a potential security vulnerability (CVE-2025-53103). Any credentials are now replaced + with `\***` before writing them to the XML report. + [[release-notes-5.13.2-junit-platform-deprecations-and-breaking-changes]] ==== Deprecations and Breaking Changes @@ -33,8 +46,8 @@ repository on GitHub. `@Nested`. * Stop reporting discovery issues for _abstract_ inner classes that contain test methods but are not annotated with `@Nested`. -* Stop reporting discovery issues for _abstract_ test methods. While they won't be - executed, it's a valid pattern to annotate them with `@Test` for documentation purposes +* Stop reporting discovery issues for _abstract_ test methods. Although they will not be + executed, it is a valid pattern to annotate them with `@Test` for documentation purposes and override them in subclasses while re-declaring the `@Test` annotation. [[release-notes-5.13.2-junit-jupiter-new-features-and-improvements]] diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.3.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.3.adoc new file mode 100644 index 000000000000..670bf3c42edf --- /dev/null +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.3.adoc @@ -0,0 +1,50 @@ +[[release-notes-5.13.3]] +== 5.13.3 + +*Date of Release:* July 4, 2025 + +*Scope:* Bug fixes and enhancements since 5.13.2 + +For a complete list of all _closed_ issues and pull requests for this release, consult the +link:{junit-framework-repo}+/milestone/100?closed=1+[5.13.3] milestone page in the JUnit +repository on GitHub. + + +[[release-notes-5.13.3-junit-platform]] +=== JUnit Platform + +No changes. + + +[[release-notes-5.13.3-junit-jupiter]] +=== JUnit Jupiter + +[[release-notes-5.13.3-junit-jupiter-bug-fixes]] +==== Bug Fixes + +* Stop reporting discovery issues for composed annotation classes that are meta-annotated + with `@Nested`. +* Stop reporting discovery issues for `DefaultImpls` classes generated by the Kotlin + compiler for interfaces with non-abstract test methods. +* When a `customReason` is supplied along with a `null` value for the default `reason` to + `ConditionEvaluationResult.disabled(String, String)`, the resulting reason is now + `"my custom reason"` instead of + `"null ++==>++ my custom reason"`. + +[[release-notes-5.13.3-junit-jupiter-new-features-and-improvements]] +==== New Features and Improvements + +* A _blank_ reason supplied to a `ConditionEvaluationResult` factory method is now treated + the same as a `null` reason, resulting in an _empty_ `Optional` returned from + `ConditionEvaluationResult.getReason()`. +* The Javadoc for factory methods in `ConditionEvaluationResult` now explicitly states + that both `null` and _blank_ values are supported for reason strings and that such + values will result in an _empty_ `Optional` returned from + `ConditionEvaluationResult.getReason()`. +* Improve message of discovery issues reported for ineffective `@Order` annotations. + + +[[release-notes-5.13.3-junit-vintage]] +=== JUnit Vintage + +No changes. diff --git a/documentation/src/docs/asciidoc/user-guide/api-evolution.adoc b/documentation/src/docs/asciidoc/user-guide/api-evolution.adoc index bac0e8b0012c..152d91e6d11e 100644 --- a/documentation/src/docs/asciidoc/user-guide/api-evolution.adoc +++ b/documentation/src/docs/asciidoc/user-guide/api-evolution.adoc @@ -40,7 +40,7 @@ value of lower stability. [[api-evolution-experimental-apis]] === Experimental APIs -The following table lists which APIs are currently designated as _experimental_ via +The following tables list which APIs are currently designated as _experimental_ via `@API(status = EXPERIMENTAL)`. Caution should be taken when relying on such APIs. include::{experimentalApisTableFile}[] @@ -48,7 +48,7 @@ include::{experimentalApisTableFile}[] [[api-evolution-deprecated-apis]] === Deprecated APIs -The following table lists which APIs are currently designated as _deprecated_ via +The following tables list which APIs are currently designated as _deprecated_ via `@API(status = DEPRECATED)`. You should avoid using deprecated APIs whenever possible, since such APIs will likely be removed in an upcoming release. diff --git a/documentation/src/tools/java/org/junit/api/tools/AbstractApiReportWriter.java b/documentation/src/tools/java/org/junit/api/tools/AbstractApiReportWriter.java index a35b60211bb4..23cdc2849c5e 100644 --- a/documentation/src/tools/java/org/junit/api/tools/AbstractApiReportWriter.java +++ b/documentation/src/tools/java/org/junit/api/tools/AbstractApiReportWriter.java @@ -16,6 +16,7 @@ import java.io.PrintWriter; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.TreeMap; @@ -52,22 +53,27 @@ public void printDeclarationInfo(PrintWriter out, Set statuses) { protected void printDeclarationSection(Set statuses, Status status, List declarations, PrintWriter out) { printDeclarationSectionHeader(statuses, status, declarations, out); - declarations.stream() // - .collect(groupingBy(Declaration::moduleName, TreeMap::new, toList())) // - .forEach((moduleName, moduleDeclarations) -> { - out.println(h4("Module " + moduleName)); - out.println(); - moduleDeclarations.stream() // - .collect(groupingBy(Declaration::packageName, TreeMap::new, toList())) // - .forEach((packageName, packageDeclarations) -> { - out.println(h5("Package " + packageName)); - out.println(); - printDeclarationTableHeader(out); - packageDeclarations.forEach(it -> printDeclarationTableRow(it, out)); - printDeclarationTableFooter(out); - out.println(); - }); - }); + Map> declarationsByModule = declarations.stream() // + .collect(groupingBy(Declaration::moduleName, TreeMap::new, toList())); + if (declarationsByModule.isEmpty()) { + out.println(paragraph("NOTE: There are currently no APIs annotated with %s.".formatted( + code("@API(status = %s)".formatted(status.name()))))); + return; + } + declarationsByModule.forEach((moduleName, moduleDeclarations) -> { + out.println(h4("Module " + moduleName)); + out.println(); + moduleDeclarations.stream() // + .collect(groupingBy(Declaration::packageName, TreeMap::new, toList())) // + .forEach((packageName, packageDeclarations) -> { + out.println(h5("Package " + packageName)); + out.println(); + printDeclarationTableHeader(out); + packageDeclarations.forEach(it -> printDeclarationTableRow(it, out)); + printDeclarationTableFooter(out); + out.println(); + }); + }); } protected void printDeclarationSectionHeader(Set statuses, Status status, List declarations, diff --git a/gradle.properties b/gradle.properties index 7a770c93d491..108a34126273 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,13 +1,13 @@ group = org.junit -version = 5.13.2 +version = 5.13.3 jupiterGroup = org.junit.jupiter platformGroup = org.junit.platform -platformVersion = 1.13.2 +platformVersion = 1.13.3 vintageGroup = org.junit.vintage -vintageVersion = 5.13.2 +vintageVersion = 5.13.3 # We need more metaspace due to apparent memory leak in Asciidoctor/JRuby org.gradle.jvmargs=-Xmx1g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 211cb2d5205f..eaa75fbb54f2 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -5,7 +5,7 @@ asciidoctorj-pdf = "2.3.19" asciidoctor-plugins = "4.0.4" # Check if workaround in documentation.gradle.kts can be removed when upgrading assertj = "3.27.3" bnd = "7.1.0" -checkstyle = "10.23.1" +checkstyle = "10.26.1" eclipse = "4.35.0" jackson = "2.19.0" jacoco = "0.8.13" @@ -98,9 +98,7 @@ develocity = { id = "com.gradle.develocity", version = "4.0.1" } foojayResolver = { id = "org.gradle.toolchains.foojay-resolver", version = "0.10.0" } gitPublish = { id = "org.ajoberstar.git-publish", version = "5.1.1" } jmh = { id = "me.champeau.jmh", version = "0.7.3" } -# Remove `sshj` constraint in gradle/plugins/publishing/build.gradle.kts when updating -# see https://github.com/jreleaser/jreleaser/issues/1900 -jreleaser = { id = "org.jreleaser", version = "1.18.0" } +jreleaser = { id = "org.jreleaser", version = "1.19.0" } # check if workaround in gradle.properties can be removed when updating kotlin = { id = "org.jetbrains.kotlin.jvm", version = "2.1.21" } plantuml = { id = "io.freefair.plantuml", version = "8.13.1" } diff --git a/gradle/plugins/publishing/build.gradle.kts b/gradle/plugins/publishing/build.gradle.kts index eea9aacdd5d1..a34fce94ea4c 100644 --- a/gradle/plugins/publishing/build.gradle.kts +++ b/gradle/plugins/publishing/build.gradle.kts @@ -8,12 +8,6 @@ dependencies { implementation("junitbuild.base:dsl-extensions") implementation(libs.plugins.jreleaser.markerCoordinates) constraints { - implementation("com.hierynomus:sshj") { - version { - require("0.40.0") - } - because("Workaround for CVE-2020-36843") - } implementation("org.eclipse.jgit:org.eclipse.jgit") { version { require("6.10.1.202505221210-r") diff --git a/junit-jupiter-api/junit-jupiter-api.gradle.kts b/junit-jupiter-api/junit-jupiter-api.gradle.kts index 402b5323eb57..2cb03aaf00dc 100644 --- a/junit-jupiter-api/junit-jupiter-api.gradle.kts +++ b/junit-jupiter-api/junit-jupiter-api.gradle.kts @@ -16,6 +16,7 @@ dependencies { compileOnly(kotlin("stdlib")) testFixturesImplementation(libs.assertj) + testFixturesImplementation(testFixtures(projects.junitPlatformCommons)) osgiVerification(projects.junitJupiterEngine) osgiVerification(projects.junitPlatformLauncher) diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AutoClose.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AutoClose.java index f0bbc4646cc7..8288be1e8416 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AutoClose.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AutoClose.java @@ -10,7 +10,7 @@ package org.junit.jupiter.api; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; @@ -78,7 +78,7 @@ @Target({ ElementType.ANNOTATION_TYPE, ElementType.FIELD }) @Retention(RetentionPolicy.RUNTIME) @Documented -@API(status = EXPERIMENTAL, since = "5.11") +@API(status = MAINTAINED, since = "5.13.3") public @interface AutoClose { /** diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/ClassTemplate.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/ClassTemplate.java index 95cf2ba436d7..faa70a48eb17 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/ClassTemplate.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/ClassTemplate.java @@ -10,7 +10,7 @@ package org.junit.jupiter.api; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; @@ -66,7 +66,7 @@ @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited -@API(status = EXPERIMENTAL, since = "5.13") +@API(status = MAINTAINED, since = "5.13.3") @Testable public @interface ClassTemplate { } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/DisplayNameGenerator.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/DisplayNameGenerator.java index d7714236f56e..e811bbee2b98 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/DisplayNameGenerator.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/DisplayNameGenerator.java @@ -12,8 +12,8 @@ import static java.util.Collections.emptyList; import static org.apiguardian.api.API.Status.DEPRECATED; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.INTERNAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import static org.junit.platform.commons.support.AnnotationSupport.findAnnotation; import static org.junit.platform.commons.support.ModifierSupport.isStatic; @@ -128,7 +128,7 @@ default String generateDisplayNameForNestedClass(Class nestedClass) { * @return the display name for the nested class; never blank * @since 5.12 */ - @API(status = EXPERIMENTAL, since = "5.12") + @API(status = MAINTAINED, since = "5.13.3") default String generateDisplayNameForNestedClass(List> enclosingInstanceTypes, Class nestedClass) { return generateDisplayNameForNestedClass(nestedClass); } @@ -177,7 +177,7 @@ default String generateDisplayNameForMethod(Class testClass, Method testMetho * @return the display name for the test; never blank * @since 5.12 */ - @API(status = EXPERIMENTAL, since = "5.12") + @API(status = MAINTAINED, since = "5.13.3") default String generateDisplayNameForMethod(List> enclosingInstanceTypes, Class testClass, Method testMethod) { return generateDisplayNameForMethod(testClass, testMethod); @@ -332,7 +332,7 @@ class IndicativeSentences implements DisplayNameGenerator { */ @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) - @API(status = EXPERIMENTAL, since = "5.13") + @API(status = MAINTAINED, since = "5.13.3") public @interface SentenceFragment { /** diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/DynamicTest.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/DynamicTest.java index d87ae1ab4f71..6eda3b567e49 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/DynamicTest.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/DynamicTest.java @@ -12,7 +12,6 @@ import static java.util.Spliterator.ORDERED; import static java.util.Spliterators.spliteratorUnknownSize; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.MAINTAINED; import java.net.URI; @@ -249,7 +248,7 @@ public static Stream stream(Stream> inputStr * @see #stream(Stream) * @see NamedExecutable */ - @API(status = EXPERIMENTAL, since = "5.11") + @API(status = MAINTAINED, since = "5.13.3") public static , E extends Executable> Stream stream( Iterator iterator) { Preconditions.notNull(iterator, "iterator must not be null"); @@ -279,7 +278,7 @@ public static , E extends Executable> Stream str * @see #stream(Iterator) * @see NamedExecutable */ - @API(status = EXPERIMENTAL, since = "5.11") + @API(status = MAINTAINED, since = "5.13.3") public static , E extends Executable> Stream stream( Stream inputStream) { Preconditions.notNull(inputStream, "inputStream must not be null"); diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/NamedExecutable.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/NamedExecutable.java index c11a631885f3..1014960d4cf9 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/NamedExecutable.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/NamedExecutable.java @@ -10,7 +10,7 @@ package org.junit.jupiter.api; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import java.util.Iterator; import java.util.stream.Stream; @@ -34,7 +34,7 @@ * @see DynamicTest#stream(Iterator) */ @FunctionalInterface -@API(status = EXPERIMENTAL, since = "5.11") +@API(status = MAINTAINED, since = "5.13.3") public interface NamedExecutable extends Named, Executable { @Override default String getName() { diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/RepeatedTest.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/RepeatedTest.java index 15c991357c4e..aa04813cab97 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/RepeatedTest.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/RepeatedTest.java @@ -10,7 +10,7 @@ package org.junit.jupiter.api; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; @@ -191,7 +191,7 @@ * @return the failure threshold; must be greater than zero and less than the * total number of repetitions */ - @API(status = EXPERIMENTAL, since = "5.10") + @API(status = MAINTAINED, since = "5.13.3") int failureThreshold() default Integer.MAX_VALUE; } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/RepetitionInfo.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/RepetitionInfo.java index a24dce3e3d6c..87a383f31ce5 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/RepetitionInfo.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/RepetitionInfo.java @@ -10,7 +10,7 @@ package org.junit.jupiter.api; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; @@ -58,7 +58,7 @@ public interface RepetitionInfo { * @since 5.10 * @see #getFailureThreshold() */ - @API(status = EXPERIMENTAL, since = "5.10") + @API(status = MAINTAINED, since = "5.13.3") int getFailureCount(); /** @@ -68,7 +68,7 @@ public interface RepetitionInfo { * @since 5.10 * @see RepeatedTest#failureThreshold() */ - @API(status = EXPERIMENTAL, since = "5.10") + @API(status = MAINTAINED, since = "5.13.3") int getFailureThreshold(); } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/TestReporter.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/TestReporter.java index 7805ab93ab29..99f7a7537065 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/TestReporter.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/TestReporter.java @@ -11,7 +11,7 @@ package org.junit.jupiter.api; import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import java.io.IOException; @@ -98,7 +98,7 @@ default void publishEntry(String value) { * {@link MediaType#APPLICATION_OCTET_STREAM} if unknown * @since 5.12 */ - @API(status = EXPERIMENTAL, since = "5.12") + @API(status = MAINTAINED, since = "5.13.3") default void publishFile(Path file, MediaType mediaType) { Preconditions.condition(Files.exists(file), () -> "file must exist: " + file); Preconditions.condition(Files.isRegularFile(file), () -> "file must be a regular file: " + file); @@ -115,7 +115,7 @@ default void publishFile(Path file, MediaType mediaType) { * @param directory the file to be attached; never {@code null} or blank * @since 5.12 */ - @API(status = EXPERIMENTAL, since = "5.12") + @API(status = MAINTAINED, since = "5.13.3") default void publishDirectory(Path directory) { Preconditions.condition(Files.exists(directory), () -> "directory must exist: " + directory); Preconditions.condition(Files.isDirectory(directory), () -> "directory must be a directory: " + directory); @@ -153,7 +153,7 @@ default void publishDirectory(Path directory) { * @param action the action to be executed to write the file; never {@code null} * @since 5.12 */ - @API(status = EXPERIMENTAL, since = "5.12") + @API(status = MAINTAINED, since = "5.13.3") default void publishFile(String name, MediaType mediaType, ThrowingConsumer action) { throw new UnsupportedOperationException(); } @@ -171,7 +171,7 @@ default void publishFile(String name, MediaType mediaType, ThrowingConsumer action) { throw new UnsupportedOperationException(); } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/Timeout.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/Timeout.java index f7081d629cda..f8338fe9a26e 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/Timeout.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/Timeout.java @@ -10,7 +10,7 @@ package org.junit.jupiter.api; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; @@ -329,7 +329,7 @@ * * @since 5.9 */ - @API(status = EXPERIMENTAL, since = "5.9") + @API(status = MAINTAINED, since = "5.13.3") String DEFAULT_TIMEOUT_THREAD_MODE_PROPERTY_NAME = "junit.jupiter.execution.timeout.thread.mode.default"; /** 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 f2b077a0b2f3..3b33756ee986 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,7 +10,7 @@ package org.junit.jupiter.api.condition; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; @@ -138,7 +138,7 @@ * @see JRE#version() * @see Runtime.Version#feature() */ - @API(status = EXPERIMENTAL, since = "5.12") + @API(status = MAINTAINED, since = "5.13.3") int minVersion() default -1; /** @@ -157,7 +157,7 @@ * @see JRE#version() * @see Runtime.Version#feature() */ - @API(status = EXPERIMENTAL, since = "5.12") + @API(status = MAINTAINED, since = "5.13.3") int maxVersion() default -1; /** 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 28281d086430..358c2e33c9b7 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,7 +10,7 @@ package org.junit.jupiter.api.condition; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; @@ -110,7 +110,7 @@ * @see JRE#version() * @see Runtime.Version#feature() */ - @API(status = EXPERIMENTAL, since = "5.12") + @API(status = MAINTAINED, since = "5.13.3") int[] versions() default {}; /** 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 d60bae33d75d..1e8f588fc671 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,7 +10,7 @@ package org.junit.jupiter.api.condition; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; @@ -138,7 +138,7 @@ * @see JRE#version() * @see Runtime.Version#feature() */ - @API(status = EXPERIMENTAL, since = "5.12") + @API(status = MAINTAINED, since = "5.13.3") int minVersion() default -1; /** @@ -157,7 +157,7 @@ * @see JRE#version() * @see Runtime.Version#feature() */ - @API(status = EXPERIMENTAL, since = "5.12") + @API(status = MAINTAINED, since = "5.13.3") int maxVersion() default -1; /** 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 5671e8c2bc51..c92938fcbd57 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,7 +10,7 @@ package org.junit.jupiter.api.condition; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; @@ -110,7 +110,7 @@ * @see JRE#version() * @see Runtime.Version#feature() */ - @API(status = EXPERIMENTAL, since = "5.12") + @API(status = MAINTAINED, since = "5.13.3") int[] versions() default {}; /** diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/AfterClassTemplateInvocationCallback.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/AfterClassTemplateInvocationCallback.java index 1a278418b2ef..6eab724eac63 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/AfterClassTemplateInvocationCallback.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/AfterClassTemplateInvocationCallback.java @@ -10,7 +10,7 @@ package org.junit.jupiter.api.extension; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import org.apiguardian.api.API; import org.junit.jupiter.api.ClassTemplate; @@ -60,7 +60,7 @@ * @see AfterTestExecutionCallback */ @FunctionalInterface -@API(status = EXPERIMENTAL, since = "5.13") +@API(status = MAINTAINED, since = "5.13.3") public interface AfterClassTemplateInvocationCallback extends Extension { /** diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/AnnotatedElementContext.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/AnnotatedElementContext.java index 19ad328fb7a4..27d8a48146b9 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/AnnotatedElementContext.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/AnnotatedElementContext.java @@ -10,7 +10,7 @@ package org.junit.jupiter.api.extension; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; @@ -33,7 +33,7 @@ * * @since 5.10 */ -@API(status = EXPERIMENTAL, since = "5.10") +@API(status = MAINTAINED, since = "5.13.3") public interface AnnotatedElementContext { /** diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/BeforeClassTemplateInvocationCallback.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/BeforeClassTemplateInvocationCallback.java index e5c3b97bea72..2f87ab1d5092 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/BeforeClassTemplateInvocationCallback.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/BeforeClassTemplateInvocationCallback.java @@ -10,7 +10,7 @@ package org.junit.jupiter.api.extension; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import org.apiguardian.api.API; import org.junit.jupiter.api.ClassTemplate; @@ -60,7 +60,7 @@ * @see AfterTestExecutionCallback */ @FunctionalInterface -@API(status = EXPERIMENTAL, since = "5.13") +@API(status = MAINTAINED, since = "5.13.3") public interface BeforeClassTemplateInvocationCallback extends Extension { /** diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ClassTemplateInvocationContext.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ClassTemplateInvocationContext.java index 00bb30b2ed61..426d2ed2d153 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ClassTemplateInvocationContext.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ClassTemplateInvocationContext.java @@ -11,7 +11,7 @@ package org.junit.jupiter.api.extension; import static java.util.Collections.emptyList; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import java.util.List; @@ -29,7 +29,7 @@ * @see ClassTemplate * @see ClassTemplateInvocationContextProvider */ -@API(status = EXPERIMENTAL, since = "5.13") +@API(status = MAINTAINED, since = "5.13.3") public interface ClassTemplateInvocationContext { /** diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ClassTemplateInvocationContextProvider.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ClassTemplateInvocationContextProvider.java index 0af499b57f14..49b3920878ac 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ClassTemplateInvocationContextProvider.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ClassTemplateInvocationContextProvider.java @@ -10,7 +10,7 @@ package org.junit.jupiter.api.extension; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import java.util.stream.Stream; @@ -58,7 +58,7 @@ * @see ClassTemplate * @see ClassTemplateInvocationContext */ -@API(status = EXPERIMENTAL, since = "5.13") +@API(status = MAINTAINED, since = "5.13.3") public interface ClassTemplateInvocationContextProvider extends Extension { /** diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ConditionEvaluationResult.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ConditionEvaluationResult.java index 316d5961813c..d0be5b70451f 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ConditionEvaluationResult.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ConditionEvaluationResult.java @@ -29,8 +29,11 @@ public class ConditionEvaluationResult { /** * Factory for creating enabled results. * - * @param reason the reason why the container or test should be enabled + * @param reason the reason why the container or test should be enabled; may + * be {@code null} or blank if the reason is unknown * @return an enabled {@code ConditionEvaluationResult} with the given reason + * or an empty reason if the reason is unknown + * @see StringUtils#isBlank(String) */ public static ConditionEvaluationResult enabled(String reason) { return new ConditionEvaluationResult(true, reason); @@ -39,8 +42,11 @@ public static ConditionEvaluationResult enabled(String reason) { /** * Factory for creating disabled results. * - * @param reason the reason why the container or test should be disabled + * @param reason the reason why the container or test should be disabled; may + * be {@code null} or blank if the reason is unknown * @return a disabled {@code ConditionEvaluationResult} with the given reason + * or an empty reason if the reason is unknown + * @see StringUtils#isBlank(String) */ public static ConditionEvaluationResult disabled(String reason) { return new ConditionEvaluationResult(false, reason); @@ -50,17 +56,27 @@ public static ConditionEvaluationResult disabled(String reason) { * Factory for creating disabled results with custom reasons * added by the user. * - * @param reason the default reason why the container or test should be disabled - * @param customReason the custom reason why the container or test should be disabled - * @return a disabled {@code ConditionEvaluationResult} with the given reasons + *

If non-blank default and custom reasons are provided, they will be + * concatenated using the format: "reason ==> customReason". + * + * @param reason the default reason why the container or test should be disabled; + * may be {@code null} or blank if the default reason is unknown + * @param customReason the custom reason why the container or test should be + * disabled; may be {@code null} or blank if the custom reason is unknown + * @return a disabled {@code ConditionEvaluationResult} with the given reason(s) + * or an empty reason if the reasons are unknown * @since 5.7 + * @see StringUtils#isBlank(String) */ @API(status = STABLE, since = "5.7") public static ConditionEvaluationResult disabled(String reason, String customReason) { + if (StringUtils.isBlank(reason)) { + return disabled(customReason); + } if (StringUtils.isBlank(customReason)) { return disabled(reason); } - return disabled(String.format("%s ==> %s", reason, customReason)); + return disabled(String.format("%s ==> %s", reason.trim(), customReason.trim())); } private final boolean enabled; @@ -69,7 +85,7 @@ public static ConditionEvaluationResult disabled(String reason, String customRea private ConditionEvaluationResult(boolean enabled, String reason) { this.enabled = enabled; - this.reason = Optional.ofNullable(reason); + this.reason = StringUtils.isNotBlank(reason) ? Optional.of(reason.trim()) : Optional.empty(); } /** diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExtensionContext.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExtensionContext.java index 0f9122024e87..7606b17ec833 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExtensionContext.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExtensionContext.java @@ -12,8 +12,8 @@ import static java.util.Collections.unmodifiableList; import static org.apiguardian.api.API.Status.DEPRECATED; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.INTERNAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import java.lang.reflect.AnnotatedElement; @@ -156,7 +156,7 @@ public interface ExtensionContext { * @since 5.12.1 * @see org.junit.platform.commons.support.AnnotationSupport#findAnnotation(Class, Class, List) */ - @API(status = EXPERIMENTAL, since = "5.12.1") + @API(status = MAINTAINED, since = "5.13.3") List> getEnclosingTestClasses(); /** @@ -412,7 +412,7 @@ default void publishReportEntry(String value) { * @since 5.12 * @see org.junit.platform.engine.EngineExecutionListener#fileEntryPublished */ - @API(status = EXPERIMENTAL, since = "5.12") + @API(status = MAINTAINED, since = "5.13.3") void publishFile(String name, MediaType mediaType, ThrowingConsumer action); /** @@ -428,7 +428,7 @@ default void publishReportEntry(String value) { * @since 5.12 * @see org.junit.platform.engine.EngineExecutionListener#fileEntryPublished */ - @API(status = EXPERIMENTAL, since = "5.12") + @API(status = MAINTAINED, since = "5.13.3") void publishDirectory(String name, ThrowingConsumer action); /** @@ -464,7 +464,7 @@ default void publishReportEntry(String value) { * @see StoreScope * @see #getStore(Namespace) */ - @API(status = EXPERIMENTAL, since = "5.13") + @API(status = MAINTAINED, since = "5.13.3") Store getStore(StoreScope scope, Namespace namespace); /** @@ -821,7 +821,7 @@ public List getParts() { * @since 5.13 * @see #getStore(StoreScope, Namespace) */ - @API(status = EXPERIMENTAL, since = "5.13") + @API(status = MAINTAINED, since = "5.13.3") enum StoreScope { /** diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExtensionContextException.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExtensionContextException.java index c31797d17362..595b2c640d72 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExtensionContextException.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExtensionContextException.java @@ -10,7 +10,7 @@ package org.junit.jupiter.api.extension; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; @@ -33,7 +33,7 @@ public ExtensionContextException(String message) { super(message); } - @API(status = EXPERIMENTAL, since = "5.10") + @API(status = MAINTAINED, since = "5.13.3") public ExtensionContextException(String message, Throwable cause) { super(message, cause); } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/MediaType.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/MediaType.java index 82513d94bcc2..2a8458e61a4e 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/MediaType.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/MediaType.java @@ -11,7 +11,7 @@ package org.junit.jupiter.api.extension; import static java.nio.charset.StandardCharsets.UTF_8; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import java.nio.charset.Charset; import java.nio.file.Path; @@ -34,7 +34,7 @@ * @see TestReporter#publishFile(String, MediaType, ThrowingConsumer) * @see ExtensionContext#publishFile(String, MediaType, ThrowingConsumer) */ -@API(status = EXPERIMENTAL, since = "5.12") +@API(status = MAINTAINED, since = "5.13.3") public class MediaType { private static final Pattern PATTERN; diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ParameterContext.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ParameterContext.java index 844b7aed9592..5ddec73b55a0 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ParameterContext.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ParameterContext.java @@ -10,7 +10,7 @@ package org.junit.jupiter.api.extension; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Annotation; @@ -94,7 +94,7 @@ default Executable getDeclaringExecutable() { * {@inheritDoc} * @since 5.10 */ - @API(status = EXPERIMENTAL, since = "5.10") + @API(status = MAINTAINED, since = "5.13.3") @Override default AnnotatedElement getAnnotatedElement() { return getParameter(); diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/PreInterruptCallback.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/PreInterruptCallback.java index 03fd96f03800..f4c23529a61f 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/PreInterruptCallback.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/PreInterruptCallback.java @@ -10,7 +10,7 @@ package org.junit.jupiter.api.extension; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import org.apiguardian.api.API; @@ -28,7 +28,7 @@ * @since 5.12 * @see org.junit.jupiter.api.Timeout */ -@API(status = EXPERIMENTAL, since = "5.12") +@API(status = MAINTAINED, since = "5.13.3") public interface PreInterruptCallback extends Extension { /** @@ -39,7 +39,7 @@ public interface PreInterruptCallback extends Extension { * * @since 5.12 */ - @API(status = EXPERIMENTAL, since = "5.12") + @API(status = MAINTAINED, since = "5.13.3") String THREAD_DUMP_ENABLED_PROPERTY_NAME = "junit.jupiter.execution.timeout.threaddump.enabled"; /** @@ -54,7 +54,7 @@ public interface PreInterruptCallback extends Extension { * @since 5.12 * @see PreInterruptContext */ - @API(status = EXPERIMENTAL, since = "5.12") + @API(status = MAINTAINED, since = "5.13.3") void beforeThreadInterrupt(PreInterruptContext preInterruptContext, ExtensionContext extensionContext) throws Exception; } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/PreInterruptContext.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/PreInterruptContext.java index 77bb98e728ff..f67df1450777 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/PreInterruptContext.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/PreInterruptContext.java @@ -10,7 +10,7 @@ package org.junit.jupiter.api.extension; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import org.apiguardian.api.API; @@ -21,7 +21,7 @@ * @since 5.12 * @see PreInterruptCallback */ -@API(status = EXPERIMENTAL, since = "5.12") +@API(status = MAINTAINED, since = "5.13.3") public interface PreInterruptContext { /** @@ -30,6 +30,6 @@ public interface PreInterruptContext { * @return the Thread; never {@code null} * @since 5.12 */ - @API(status = EXPERIMENTAL, since = "5.12") + @API(status = MAINTAINED, since = "5.13.3") Thread getThreadToInterrupt(); } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/TemplateInvocationValidationException.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/TemplateInvocationValidationException.java index 94cad7ab8677..6a0c18aa508e 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/TemplateInvocationValidationException.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/TemplateInvocationValidationException.java @@ -10,7 +10,7 @@ package org.junit.jupiter.api.extension; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; @@ -24,7 +24,7 @@ * * @since 5.13 */ -@API(status = EXPERIMENTAL, since = "5.13") +@API(status = MAINTAINED, since = "5.13.3") public class TemplateInvocationValidationException extends JUnitException { private static final long serialVersionUID = 1L; diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/TestInstantiationAwareExtension.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/TestInstantiationAwareExtension.java index 7f4847304c06..2045d264080f 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/TestInstantiationAwareExtension.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/TestInstantiationAwareExtension.java @@ -11,7 +11,7 @@ package org.junit.jupiter.api.extension; import static org.apiguardian.api.API.Status.DEPRECATED; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import org.apiguardian.api.API; import org.junit.jupiter.api.TestInstance; @@ -31,7 +31,7 @@ * @see TestInstancePostProcessor * @see TestInstanceFactory */ -@API(status = EXPERIMENTAL, since = "5.12") +@API(status = MAINTAINED, since = "5.13.3") public interface TestInstantiationAwareExtension extends Extension { /** @@ -89,7 +89,7 @@ public interface TestInstantiationAwareExtension extends Extension { * configuration parameters; never {@code null} * @since 5.12 */ - @API(status = EXPERIMENTAL, since = "5.12") + @API(status = MAINTAINED, since = "5.13.3") default ExtensionContextScope getTestInstantiationExtensionContextScope(ExtensionContext rootContext) { return ExtensionContextScope.DEFAULT; } @@ -102,7 +102,7 @@ default ExtensionContextScope getTestInstantiationExtensionContextScope(Extensio * @since 5.12 * @see TestInstantiationAwareExtension#getTestInstantiationExtensionContextScope */ - @API(status = EXPERIMENTAL, since = "5.12") + @API(status = MAINTAINED, since = "5.13.3") enum ExtensionContextScope { /** diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/TestTemplateInvocationContext.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/TestTemplateInvocationContext.java index 1d74bed2dd7d..a49e27348d2f 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/TestTemplateInvocationContext.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/TestTemplateInvocationContext.java @@ -11,7 +11,7 @@ package org.junit.jupiter.api.extension; import static java.util.Collections.emptyList; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import java.util.List; @@ -77,7 +77,7 @@ default List getAdditionalExtensions() { * @param context The invocation-level extension context. * @since 5.13 */ - @API(status = EXPERIMENTAL, since = "5.13") + @API(status = MAINTAINED, since = "5.13.3") default void prepareInvocation(ExtensionContext context) { } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/TestTemplateInvocationContextProvider.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/TestTemplateInvocationContextProvider.java index f4a64479cde9..90cb4b79f033 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/TestTemplateInvocationContextProvider.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/TestTemplateInvocationContextProvider.java @@ -10,7 +10,7 @@ package org.junit.jupiter.api.extension; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import java.util.stream.Stream; @@ -111,7 +111,7 @@ public interface TestTemplateInvocationContextProvider extends Extension { * * @since 5.12 */ - @API(status = EXPERIMENTAL, since = "5.12") + @API(status = MAINTAINED, since = "5.13.3") default boolean mayReturnZeroTestTemplateInvocationContexts(ExtensionContext context) { return false; } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/io/TempDir.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/io/TempDir.java index 4b9053ba237d..f3d778f26fae 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/io/TempDir.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/io/TempDir.java @@ -11,7 +11,7 @@ package org.junit.jupiter.api.io; import static org.apiguardian.api.API.Status.DEPRECATED; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import java.io.File; @@ -120,7 +120,7 @@ * * @since 5.10 */ - @API(status = EXPERIMENTAL, since = "5.10") + @API(status = MAINTAINED, since = "5.13.3") String DEFAULT_FACTORY_PROPERTY_NAME = "junit.jupiter.tempdir.factory.default"; /** @@ -142,7 +142,7 @@ * @since 5.10 * @see TempDirFactory */ - @API(status = EXPERIMENTAL, since = "5.10") + @API(status = MAINTAINED, since = "5.13.3") Class factory() default TempDirFactory.class; /** @@ -176,7 +176,7 @@ * * @since 5.9 */ - @API(status = EXPERIMENTAL, since = "5.9") + @API(status = MAINTAINED, since = "5.13.3") String DEFAULT_CLEANUP_MODE_PROPERTY_NAME = "junit.jupiter.tempdir.cleanup.mode.default"; /** diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/io/TempDirFactory.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/io/TempDirFactory.java index d5bbce4a4e2f..52b6713fa4a7 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/io/TempDirFactory.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/io/TempDirFactory.java @@ -10,7 +10,7 @@ package org.junit.jupiter.api.io; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import java.io.Closeable; import java.io.IOException; @@ -45,7 +45,7 @@ * @see TempDir @TempDir */ @FunctionalInterface -@API(status = EXPERIMENTAL, since = "5.10") +@API(status = MAINTAINED, since = "5.13.3") public interface TempDirFactory extends Closeable { /** @@ -73,7 +73,7 @@ default void close() throws IOException { /** * Standard {@link TempDirFactory} implementation which delegates to - * {@link Files#createTempDirectory} using {@code "junit-,"} as prefix. + * {@link Files#createTempDirectory} using {@code "junit-"} as prefix. * *

The created temporary directory is always created in the default * file system with the system's default temporary directory as its parent. diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/parallel/Execution.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/parallel/Execution.java index d1c53ca87d96..f46680ca5b00 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/parallel/Execution.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/parallel/Execution.java @@ -10,7 +10,7 @@ package org.junit.jupiter.api.parallel; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.ElementType; @@ -77,7 +77,7 @@ * * @since 5.4 */ - @API(status = EXPERIMENTAL, since = "5.9") + @API(status = MAINTAINED, since = "5.13.3") String DEFAULT_EXECUTION_MODE_PROPERTY_NAME = "junit.jupiter.execution.parallel.mode.default"; /** @@ -96,7 +96,7 @@ * * @since 5.4 */ - @API(status = EXPERIMENTAL, since = "5.9") + @API(status = MAINTAINED, since = "5.13.3") String DEFAULT_CLASSES_EXECUTION_MODE_PROPERTY_NAME = "junit.jupiter.execution.parallel.mode.classes.default"; /** diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/parallel/ResourceLock.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/parallel/ResourceLock.java index 370e0c679a4f..19ef61206ca4 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/parallel/ResourceLock.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/parallel/ResourceLock.java @@ -10,7 +10,7 @@ package org.junit.jupiter.api.parallel; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.ElementType; @@ -118,7 +118,7 @@ * @see ResourceLocksProvider.Lock * @since 5.12 */ - @API(status = EXPERIMENTAL, since = "5.12") + @API(status = MAINTAINED, since = "5.13.3") Class[] providers() default {}; /** @@ -132,7 +132,7 @@ * @see ResourceLockTarget * @since 5.12 */ - @API(status = EXPERIMENTAL, since = "5.12") + @API(status = MAINTAINED, since = "5.13.3") ResourceLockTarget target() default ResourceLockTarget.SELF; } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/parallel/ResourceLockTarget.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/parallel/ResourceLockTarget.java index 94a7a0bf7d68..69a7d7d2e7ed 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/parallel/ResourceLockTarget.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/parallel/ResourceLockTarget.java @@ -10,7 +10,7 @@ package org.junit.jupiter.api.parallel; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import org.apiguardian.api.API; @@ -20,7 +20,7 @@ * @since 5.12 * @see ResourceLock#target() */ -@API(status = EXPERIMENTAL, since = "5.12") +@API(status = MAINTAINED, since = "5.13.3") public enum ResourceLockTarget { /** diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/parallel/ResourceLocksProvider.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/parallel/ResourceLocksProvider.java index 2cffc5d6101f..7708b8b5b9e3 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/parallel/ResourceLocksProvider.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/parallel/ResourceLocksProvider.java @@ -11,7 +11,7 @@ package org.junit.jupiter.api.parallel; import static java.util.Collections.emptySet; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.reflect.Method; import java.util.List; @@ -40,7 +40,7 @@ * @see ResourceAccessMode * @see Lock */ -@API(status = EXPERIMENTAL, since = "5.12") +@API(status = MAINTAINED, since = "5.13.3") public interface ResourceLocksProvider { /** diff --git a/junit-jupiter-api/src/main/kotlin/org/junit/jupiter/api/Assertions.kt b/junit-jupiter-api/src/main/kotlin/org/junit/jupiter/api/Assertions.kt index ce93a2fdd56b..81ad3e12dd0e 100644 --- a/junit-jupiter-api/src/main/kotlin/org/junit/jupiter/api/Assertions.kt +++ b/junit-jupiter-api/src/main/kotlin/org/junit/jupiter/api/Assertions.kt @@ -12,7 +12,7 @@ package org.junit.jupiter.api import org.apiguardian.api.API -import org.apiguardian.api.API.Status.EXPERIMENTAL +import org.apiguardian.api.API.Status.MAINTAINED import org.apiguardian.api.API.Status.STABLE import org.junit.jupiter.api.function.Executable import org.junit.jupiter.api.function.ThrowingSupplier @@ -36,7 +36,7 @@ fun fail( * @see Assertions.fail */ @OptIn(ExperimentalContracts::class) -@API(since = "5.12", status = EXPERIMENTAL) +@API(status = MAINTAINED, since = "5.13.3") @JvmName("fail_nonNullableLambda") fun fail(message: () -> String): Nothing { contract { @@ -122,7 +122,7 @@ fun assertAll( * @see Assertions.assertNull */ @OptIn(ExperimentalContracts::class) -@API(since = "5.12", status = EXPERIMENTAL) +@API(status = MAINTAINED, since = "5.13.3") fun assertNull(actual: Any?) { contract { returns() implies (actual == null) @@ -144,7 +144,7 @@ fun assertNull(actual: Any?) { * @see Assertions.assertNull */ @OptIn(ExperimentalContracts::class) -@API(since = "5.12", status = EXPERIMENTAL) +@API(status = MAINTAINED, since = "5.13.3") fun assertNull( actual: Any?, message: String @@ -169,7 +169,7 @@ fun assertNull( * @see Assertions.assertNull */ @OptIn(ExperimentalContracts::class) -@API(since = "5.12", status = EXPERIMENTAL) +@API(status = MAINTAINED, since = "5.13.3") fun assertNull( actual: Any?, messageSupplier: () -> String @@ -196,7 +196,7 @@ fun assertNull( * @see Assertions.assertNotNull */ @OptIn(ExperimentalContracts::class) -@API(since = "5.12", status = EXPERIMENTAL) +@API(status = MAINTAINED, since = "5.13.3") fun assertNotNull(actual: Any?) { contract { returns() implies (actual != null) @@ -218,7 +218,7 @@ fun assertNotNull(actual: Any?) { * @see Assertions.assertNotNull */ @OptIn(ExperimentalContracts::class) -@API(since = "5.12", status = EXPERIMENTAL) +@API(status = MAINTAINED, since = "5.13.3") fun assertNotNull( actual: Any?, message: String @@ -243,7 +243,7 @@ fun assertNotNull( * @see Assertions.assertNotNull */ @OptIn(ExperimentalContracts::class) -@API(since = "5.12", status = EXPERIMENTAL) +@API(status = MAINTAINED, since = "5.13.3") fun assertNotNull( actual: Any?, messageSupplier: () -> String @@ -568,7 +568,7 @@ fun assertTimeoutPreemptively( * @since 5.11 */ @OptIn(ExperimentalContracts::class) -@API(status = EXPERIMENTAL, since = "5.11") +@API(status = MAINTAINED, since = "5.13.3") inline fun assertInstanceOf( actualValue: Any?, message: String? = null @@ -593,7 +593,7 @@ inline fun assertInstanceOf( * @since 5.11 */ @OptIn(ExperimentalContracts::class) -@API(status = EXPERIMENTAL, since = "5.11") +@API(status = MAINTAINED, since = "5.13.3") inline fun assertInstanceOf( actualValue: Any?, noinline message: () -> String 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 f664e0df2e74..d27ba5450855 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 @@ -8,7 +8,7 @@ ${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.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import java.lang.reflect.Method; @@ -52,7 +52,7 @@ public enum JRE { * * @since 5.12 */ - @API(status = EXPERIMENTAL, since = "5.12") + @API(status = MAINTAINED, since = "5.13.3") UNDEFINED(-1), @for(var jre : jres) /** @@ -153,7 +153,7 @@ public enum JRE { * @see Runtime.Version#feature() * @see #currentVersionNumber() */ - @API(status = EXPERIMENTAL, since = "5.12") + @API(status = MAINTAINED, since = "5.13.3") public int version() { return this.version; } @@ -204,7 +204,7 @@ public enum JRE { * @see Runtime.Version#feature() * @see #currentJre() */ - @API(status = EXPERIMENTAL, since = "5.12") + @API(status = MAINTAINED, since = "5.13.3") public static int currentVersionNumber() { return CURRENT_VERSION; } @@ -218,7 +218,7 @@ public enum JRE { * @since 5.12 * @see Runtime.Version#feature() */ - @API(status = EXPERIMENTAL, since = "5.12") + @API(status = MAINTAINED, since = "5.13.3") public static boolean isCurrentVersion(int version) { return version == CURRENT_VERSION; } diff --git a/junit-jupiter-api/src/testFixtures/java/org/junit/jupiter/api/extension/DisabledInEclipse.java b/junit-jupiter-api/src/testFixtures/java/org/junit/jupiter/api/extension/DisabledInEclipse.java new file mode 100644 index 000000000000..ec93252305bb --- /dev/null +++ b/junit-jupiter-api/src/testFixtures/java/org/junit/jupiter/api/extension/DisabledInEclipse.java @@ -0,0 +1,28 @@ +/* + * Copyright 2015-2025 the original author or authors. + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v2.0 which + * accompanies this distribution and is available at + * + * https://www.eclipse.org/legal/epl-v20.html + */ + +package org.junit.jupiter.api.extension; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.junit.jupiter.api.condition.DisabledIf; + +/** + * @see org.junit.platform.commons.test.IdeUtils#runningInEclipse() + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.TYPE, ElementType.METHOD }) +@DisabledIf("org.junit.platform.commons.test.IdeUtils#runningInEclipse()") +public @interface DisabledInEclipse { + String value() default ""; +} diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/Constants.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/Constants.java index 321a707be394..92baf369fd01 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/Constants.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/Constants.java @@ -11,7 +11,7 @@ package org.junit.jupiter.engine; import static org.apiguardian.api.API.Status.DEPRECATED; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import static org.junit.platform.engine.support.hierarchical.DefaultParallelExecutionConfigurationStrategy.CONFIG_CUSTOM_CLASS_PROPERTY_NAME; import static org.junit.platform.engine.support.hierarchical.DefaultParallelExecutionConfigurationStrategy.CONFIG_DYNAMIC_FACTOR_PROPERTY_NAME; @@ -190,7 +190,7 @@ public final class Constants { * * @since 5.12 */ - @API(status = EXPERIMENTAL, since = "5.12") + @API(status = MAINTAINED, since = "5.13.3") public static final String EXTENSIONS_TIMEOUT_THREAD_DUMP_ENABLED_PROPERTY_NAME = JupiterConfiguration.EXTENSIONS_TIMEOUT_THREAD_DUMP_ENABLED_PROPERTY_NAME; /** @@ -217,7 +217,7 @@ public final class Constants { * * @since 5.13 */ - @API(status = EXPERIMENTAL, since = "5.13") + @API(status = MAINTAINED, since = "5.13.3") public static final String CLOSING_STORED_AUTO_CLOSEABLE_ENABLED_PROPERTY_NAME = JupiterConfiguration.CLOSING_STORED_AUTO_CLOSEABLE_ENABLED_PROPERTY_NAME; /** @@ -276,7 +276,7 @@ public final class Constants { * * @since 5.10 */ - @API(status = EXPERIMENTAL, since = "5.10") + @API(status = MAINTAINED, since = "5.13.3") public static final String PARALLEL_CONFIG_FIXED_MAX_POOL_SIZE_PROPERTY_NAME = PARALLEL_CONFIG_PREFIX + CONFIG_FIXED_MAX_POOL_SIZE_PROPERTY_NAME; @@ -294,7 +294,7 @@ public final class Constants { * * @since 5.10 */ - @API(status = EXPERIMENTAL, since = "5.10") + @API(status = MAINTAINED, since = "5.13.3") public static final String PARALLEL_CONFIG_FIXED_SATURATE_PROPERTY_NAME = PARALLEL_CONFIG_PREFIX + CONFIG_FIXED_SATURATE_PROPERTY_NAME; @@ -452,7 +452,7 @@ public final class Constants { * @see Timeout * @see Timeout.ThreadMode */ - @API(status = EXPERIMENTAL, since = "5.9") + @API(status = MAINTAINED, since = "5.13.3") public static final String DEFAULT_TIMEOUT_THREAD_MODE_PROPERTY_NAME = Timeout.DEFAULT_TIMEOUT_THREAD_MODE_PROPERTY_NAME; /** @@ -462,7 +462,7 @@ public final class Constants { * @since 5.10 * @see TempDir#DEFAULT_FACTORY_PROPERTY_NAME */ - @API(status = EXPERIMENTAL, since = "5.10") + @API(status = MAINTAINED, since = "5.13.3") public static final String DEFAULT_TEMP_DIR_FACTORY_PROPERTY_NAME = TempDir.DEFAULT_FACTORY_PROPERTY_NAME; /** @@ -472,7 +472,7 @@ public final class Constants { * @since 5.12 * @see org.junit.jupiter.api.extension.TestInstantiationAwareExtension */ - @API(status = EXPERIMENTAL, since = "5.12") + @API(status = MAINTAINED, since = "5.13.3") public static final String DEFAULT_TEST_CLASS_INSTANCE_CONSTRUCTION_EXTENSION_CONTEXT_SCOPE_PROPERTY_NAME = ExtensionContextScope.DEFAULT_SCOPE_PROPERTY_NAME; private Constants() { diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/ClassOrderingVisitor.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/ClassOrderingVisitor.java index e64063088600..cfb25614851e 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/ClassOrderingVisitor.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/ClassOrderingVisitor.java @@ -28,7 +28,6 @@ import org.junit.platform.engine.DiscoveryIssue; import org.junit.platform.engine.DiscoveryIssue.Severity; import org.junit.platform.engine.TestDescriptor; -import org.junit.platform.engine.support.descriptor.ClassSource; import org.junit.platform.engine.support.discovery.DiscoveryIssueReporter; import org.junit.platform.engine.support.discovery.DiscoveryIssueReporter.Condition; @@ -49,11 +48,12 @@ class ClassOrderingVisitor extends AbstractOrderingVisitor { this.globalOrderer = createGlobalOrderer(configuration); this.noOrderAnnotation = issueReporter.createReportingCondition( testDescriptor -> !isAnnotated(testDescriptor.getTestClass(), Order.class), testDescriptor -> { - String message = String.format( - "Ineffective @Order annotation on class '%s'. It will not be applied because ClassOrderer.OrderAnnotation is not in use.", - testDescriptor.getTestClass().getName()); + String message = String.format("Ineffective @Order annotation on class '%s'. ", + testDescriptor.getTestClass().getName()) + + "It will not be applied because ClassOrderer.OrderAnnotation is not in use. " + + "Note that the annotation may be either directly present or meta-present on the class."; return DiscoveryIssue.builder(Severity.INFO, message) // - .source(ClassSource.from(testDescriptor.getTestClass())) // + .source(testDescriptor.getSource()) // .build(); }); } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/ClassSelectorResolver.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/ClassSelectorResolver.java index 0449d12abb09..8592f4ab0cd8 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/ClassSelectorResolver.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/ClassSelectorResolver.java @@ -15,6 +15,7 @@ import static java.util.stream.Collectors.toCollection; import static java.util.stream.Collectors.toSet; import static org.junit.jupiter.engine.descriptor.NestedClassTestDescriptor.getEnclosingTestClasses; +import static org.junit.jupiter.engine.discovery.predicates.TestClassPredicates.NestedClassInvalidityReason.NOT_INNER; import static org.junit.platform.commons.support.HierarchyTraversalMode.TOP_DOWN; import static org.junit.platform.commons.support.ReflectionSupport.findMethods; import static org.junit.platform.commons.util.FunctionUtils.where; @@ -45,6 +46,7 @@ import org.junit.jupiter.engine.descriptor.NestedClassTestDescriptor; import org.junit.jupiter.engine.descriptor.TestClassAware; import org.junit.jupiter.engine.discovery.predicates.TestClassPredicates; +import org.junit.jupiter.engine.discovery.predicates.TestClassPredicates.NestedClassInvalidityReason; import org.junit.platform.commons.support.ReflectionSupport; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.commons.util.ReflectionUtils.CycleErrorHandling; @@ -86,13 +88,22 @@ public Resolution resolve(ClassSelector selector, Context context) { if (this.predicates.isAnnotatedWithNested.test(testClass)) { // Class name filter is not applied to nested test classes - if (this.predicates.isValidNestedTestClass(testClass)) { + NestedClassInvalidityReason invalidityReason = this.predicates.validateNestedTestClass(testClass); + if (invalidityReason == null) { return toResolution( context.addToParent(() -> DiscoverySelectors.selectClass(testClass.getEnclosingClass()), parent -> Optional.of(newMemberClassTestDescriptor(parent, testClass)))); } + if (invalidityReason == NOT_INNER) { + return resolveStandaloneTestClass(context, testClass); + } + return unresolved(); } - else if (isAcceptedStandaloneTestClass(testClass)) { + return resolveStandaloneTestClass(context, testClass); + } + + private Resolution resolveStandaloneTestClass(Context context, Class testClass) { + if (isAcceptedStandaloneTestClass(testClass)) { return toResolution( context.addToParent(parent -> Optional.of(newStandaloneClassTestDescriptor(parent, testClass)))); } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/MethodOrderingVisitor.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/MethodOrderingVisitor.java index d1aeb152cc30..b6ecbf0932a5 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/MethodOrderingVisitor.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/MethodOrderingVisitor.java @@ -31,7 +31,6 @@ import org.junit.platform.engine.DiscoveryIssue; import org.junit.platform.engine.DiscoveryIssue.Severity; import org.junit.platform.engine.TestDescriptor; -import org.junit.platform.engine.support.descriptor.MethodSource; import org.junit.platform.engine.support.discovery.DiscoveryIssueReporter; import org.junit.platform.engine.support.discovery.DiscoveryIssueReporter.Condition; @@ -51,11 +50,12 @@ class MethodOrderingVisitor extends AbstractOrderingVisitor { this.configuration = configuration; this.noOrderAnnotation = issueReporter.createReportingCondition( testDescriptor -> !isAnnotated(testDescriptor.getTestMethod(), Order.class), testDescriptor -> { - String message = String.format( - "Ineffective @Order annotation on method '%s'. It will not be applied because MethodOrderer.OrderAnnotation is not in use.", - testDescriptor.getTestMethod().toGenericString()); + String message = String.format("Ineffective @Order annotation on method '%s'. ", + testDescriptor.getTestMethod().toGenericString()) + + "It will not be applied because MethodOrderer.OrderAnnotation is not in use. " + + "Note that the annotation may be either directly present or meta-present on the method."; return DiscoveryIssue.builder(Severity.INFO, message) // - .source(MethodSource.from(testDescriptor.getTestMethod())) // + .source(testDescriptor.getSource()) // .build(); }); this.methodsBeforeNestedClassesOrderer = createMethodsBeforeNestedClassesOrderer(); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/predicates/TestClassPredicates.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/predicates/TestClassPredicates.java index 8d3910a7418f..67d28bd30e57 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/predicates/TestClassPredicates.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/predicates/TestClassPredicates.java @@ -15,10 +15,12 @@ import static org.junit.platform.commons.support.ModifierSupport.isAbstract; import static org.junit.platform.commons.support.ModifierSupport.isNotAbstract; import static org.junit.platform.commons.support.ModifierSupport.isNotPrivate; +import static org.junit.platform.commons.util.KotlinReflectionUtils.isKotlinInterfaceDefaultImplsClass; import static org.junit.platform.commons.util.ReflectionUtils.isInnerClass; import static org.junit.platform.commons.util.ReflectionUtils.isMethodPresent; import static org.junit.platform.commons.util.ReflectionUtils.isNestedClassPresent; +import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.HashSet; import java.util.Set; @@ -42,8 +44,9 @@ @API(status = INTERNAL, since = "5.13") public class TestClassPredicates { - public final Predicate> isAnnotatedWithNested = testClass -> isAnnotated(testClass, Nested.class); - public final Predicate> isAnnotatedWithClassTemplate = testClass -> isAnnotated(testClass, + public final Predicate> isAnnotatedWithNested = candidate -> isAnnotatedButNotComposed(candidate, + Nested.class); + public final Predicate> isAnnotatedWithClassTemplate = candidate -> isAnnotatedButNotComposed(candidate, ClassTemplate.class); public final Predicate> isAnnotatedWithNestedAndValid = candidate -> this.isAnnotatedWithNested.test( @@ -52,15 +55,16 @@ public class TestClassPredicates { candidate) || looksLikeIntendedTestClass(candidate); public final Predicate isTestOrTestFactoryOrTestTemplateMethod; - private final Condition> isValidNestedTestClass; + private final Condition> isNotPrivateUnlessAbstractNestedClass; + private final Condition> isInnerNestedClass; private final Condition> isValidStandaloneTestClass; public TestClassPredicates(DiscoveryIssueReporter issueReporter) { this.isTestOrTestFactoryOrTestTemplateMethod = new IsTestMethod(issueReporter) // .or(new IsTestFactoryMethod(issueReporter)) // .or(new IsTestTemplateMethod(issueReporter)); - this.isValidNestedTestClass = isNotPrivateUnlessAbstract("@Nested", issueReporter) // - .and(isInner(issueReporter)); + this.isNotPrivateUnlessAbstractNestedClass = isNotPrivateUnlessAbstract("@Nested", issueReporter); + this.isInnerNestedClass = isInner(issueReporter); this.isValidStandaloneTestClass = isNotPrivateUnlessAbstract("Test", issueReporter) // .and(isNotLocal(issueReporter)) // .and(isNotInnerUnlessAbstract(issueReporter)) // @@ -72,7 +76,7 @@ public boolean looksLikeIntendedTestClass(Class candidate) { } private boolean looksLikeIntendedTestClass(Class candidate, Set> seen) { - if (seen.add(candidate)) { + if (seen.add(candidate) && !isKotlinInterfaceDefaultImplsClass(candidate)) { return this.isAnnotatedWithClassTemplate.test(candidate) // || hasTestOrTestFactoryOrTestTemplateMethods(candidate) // || hasNestedTests(candidate, seen); @@ -81,8 +85,16 @@ private boolean looksLikeIntendedTestClass(Class candidate, Set> see } public boolean isValidNestedTestClass(Class candidate) { - return this.isValidNestedTestClass.check(candidate) // - && isNotAbstract(candidate); + return validateNestedTestClass(candidate) == null; + } + + public NestedClassInvalidityReason validateNestedTestClass(Class candidate) { + boolean isInner = this.isInnerNestedClass.check(candidate); + boolean isNotPrivateUnlessAbstract = this.isNotPrivateUnlessAbstractNestedClass.check(candidate); + if (isNotPrivateUnlessAbstract && isNotAbstract(candidate)) { + return isInner ? null : NestedClassInvalidityReason.NOT_INNER; + } + return NestedClassInvalidityReason.OTHER; } public boolean isValidStandaloneTestClass(Class candidate) { @@ -121,9 +133,13 @@ private static Condition> isNotLocal(DiscoveryIssueReporter issueReport private static Condition> isInner(DiscoveryIssueReporter issueReporter) { return issueReporter.createReportingCondition(ReflectionUtils::isInnerClass, testClass -> { if (testClass.getEnclosingClass() == null) { - return createIssue("@Nested", testClass, "must not be a top-level class"); + return createIssue("Top-level", testClass, "must not be annotated with @Nested", + "It will be executed anyway for backward compatibility. " + + "You should remove the @Nested annotation to resolve this warning."); } - return createIssue("@Nested", testClass, "must not be static"); + return createIssue("@Nested", testClass, "must not be static", + "It will only be executed if discovered as a standalone test class. " + + "You should remove the annotation or make it non-static to resolve this warning."); }); } @@ -138,10 +154,22 @@ private static Condition> isNotAnonymous(DiscoveryIssueReporter issueRe } private static DiscoveryIssue createIssue(String prefix, Class testClass, String detailMessage) { - String message = String.format("%s class '%s' %s. It will not be executed.", prefix, testClass.getName(), - detailMessage); + return createIssue(prefix, testClass, detailMessage, "It will not be executed."); + } + + private static DiscoveryIssue createIssue(String prefix, Class testClass, String detailMessage, String effect) { + String message = String.format("%s class '%s' %s. %s", prefix, testClass.getName(), detailMessage, effect); return DiscoveryIssue.builder(DiscoveryIssue.Severity.WARNING, message) // .source(ClassSource.from(testClass)) // .build(); } + + private static boolean isAnnotatedButNotComposed(Class candidate, Class annotationType) { + return !candidate.isAnnotation() && isAnnotated(candidate, annotationType); + } + + @API(status = INTERNAL, since = "5.13.3") + public enum NestedClassInvalidityReason { + NOT_INNER, OTHER + } } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/AfterParameterizedClassInvocation.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/AfterParameterizedClassInvocation.java index b7cb8fd6341a..1beb3b1b53e8 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/AfterParameterizedClassInvocation.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/AfterParameterizedClassInvocation.java @@ -10,7 +10,7 @@ package org.junit.jupiter.params; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; @@ -157,7 +157,7 @@ @Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented -@API(status = EXPERIMENTAL, since = "5.13") +@API(status = MAINTAINED, since = "5.13.3") @ClassTemplateInvocationLifecycleMethod(classTemplateAnnotation = ParameterizedClass.class, lifecycleMethodAnnotation = AfterParameterizedClassInvocation.class) public @interface AfterParameterizedClassInvocation { diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ArgumentCountValidationMode.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ArgumentCountValidationMode.java index 2188d8a170b1..c4ae05782365 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ArgumentCountValidationMode.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ArgumentCountValidationMode.java @@ -10,6 +10,8 @@ package org.junit.jupiter.params; +import static org.apiguardian.api.API.Status.MAINTAINED; + import org.apiguardian.api.API; import org.junit.jupiter.params.provider.ArgumentsSource; @@ -28,7 +30,7 @@ * @see ParameterizedClass#argumentCountValidation() * @see ParameterizedTest#argumentCountValidation() */ -@API(status = API.Status.EXPERIMENTAL, since = "5.12") +@API(status = MAINTAINED, since = "5.13.3") public enum ArgumentCountValidationMode { /** diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/BeforeParameterizedClassInvocation.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/BeforeParameterizedClassInvocation.java index 1391fd5a240e..c02fd72f48df 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/BeforeParameterizedClassInvocation.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/BeforeParameterizedClassInvocation.java @@ -10,7 +10,7 @@ package org.junit.jupiter.params; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; @@ -158,7 +158,7 @@ @Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented -@API(status = EXPERIMENTAL, since = "5.13") +@API(status = MAINTAINED, since = "5.13.3") @ClassTemplateInvocationLifecycleMethod(classTemplateAnnotation = ParameterizedClass.class, lifecycleMethodAnnotation = BeforeParameterizedClassInvocation.class) public @interface BeforeParameterizedClassInvocation { diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/Parameter.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/Parameter.java index 70325ff71746..1296d8474707 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/Parameter.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/Parameter.java @@ -10,7 +10,7 @@ package org.junit.jupiter.params; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; @@ -41,7 +41,7 @@ @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.ANNOTATION_TYPE, ElementType.FIELD }) @Documented -@API(status = EXPERIMENTAL, since = "5.13") +@API(status = MAINTAINED, since = "5.13.3") public @interface Parameter { /** diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedClass.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedClass.java index cf64caaab50d..3377976ff018 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedClass.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedClass.java @@ -10,7 +10,7 @@ package org.junit.jupiter.params; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; @@ -149,7 +149,7 @@ @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited -@API(status = EXPERIMENTAL, since = "5.13") +@API(status = MAINTAINED, since = "5.13.3") @ClassTemplate @ExtendWith(ParameterizedClassExtension.class) @SuppressWarnings("exports") diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationConstants.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationConstants.java index 04eff295b1a2..d3e171868873 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationConstants.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationConstants.java @@ -10,7 +10,6 @@ package org.junit.jupiter.params; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.MAINTAINED; import org.apiguardian.api.API; @@ -88,7 +87,7 @@ public class ParameterizedInvocationConstants { * @see #ARGUMENT_SET_NAME_OR_ARGUMENTS_WITH_NAMES_PLACEHOLDER * @see org.junit.jupiter.params.provider.Arguments#argumentSet(String, Object...) */ - @API(status = EXPERIMENTAL, since = "5.11") + @API(status = MAINTAINED, since = "5.13.3") public static final String ARGUMENT_SET_NAME_PLACEHOLDER = "{argumentSetName}"; /** @@ -106,7 +105,7 @@ public class ParameterizedInvocationConstants { * @see #DEFAULT_DISPLAY_NAME * @see org.junit.jupiter.params.provider.Arguments#argumentSet(String, Object...) */ - @API(status = EXPERIMENTAL, since = "5.11") + @API(status = MAINTAINED, since = "5.13.3") public static final String ARGUMENT_SET_NAME_OR_ARGUMENTS_WITH_NAMES_PLACEHOLDER = "{argumentSetNameOrArgumentsWithNames}"; /** diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedTest.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedTest.java index eb841a9bdc5b..129bde582290 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedTest.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedTest.java @@ -11,7 +11,7 @@ package org.junit.jupiter.params; import static org.apiguardian.api.API.Status.DEPRECATED; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; @@ -313,7 +313,7 @@ * * @since 5.12 */ - @API(status = EXPERIMENTAL, since = "5.12") + @API(status = MAINTAINED, since = "5.13.3") boolean allowZeroInvocations() default false; /** @@ -334,7 +334,7 @@ * @since 5.12 * @see ArgumentCountValidationMode */ - @API(status = EXPERIMENTAL, since = "5.12") + @API(status = MAINTAINED, since = "5.13.3") ArgumentCountValidationMode argumentCountValidation() default ArgumentCountValidationMode.DEFAULT; } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/ArgumentsAggregator.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/ArgumentsAggregator.java index 905b69e8fe33..6c2d81c633e3 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/ArgumentsAggregator.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/ArgumentsAggregator.java @@ -10,7 +10,7 @@ package org.junit.jupiter.params.aggregator; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; @@ -82,7 +82,7 @@ Object aggregateArguments(ArgumentsAccessor accessor, ParameterContext context) * aggregation * @since 5.13 */ - @API(status = EXPERIMENTAL, since = "5.13") + @API(status = MAINTAINED, since = "5.13.3") default Object aggregateArguments(ArgumentsAccessor accessor, FieldContext context) throws ArgumentsAggregationException { throw new JUnitException( diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/SimpleArgumentsAggregator.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/SimpleArgumentsAggregator.java index 7537e5a64e46..98f998b38d31 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/SimpleArgumentsAggregator.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/SimpleArgumentsAggregator.java @@ -10,7 +10,7 @@ package org.junit.jupiter.params.aggregator; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.AnnotatedElementContext; @@ -25,7 +25,7 @@ * @since 5.0 * @see ArgumentsAggregator */ -@API(status = EXPERIMENTAL, since = "5.13") +@API(status = MAINTAINED, since = "5.13.3") public abstract class SimpleArgumentsAggregator implements ArgumentsAggregator { public SimpleArgumentsAggregator() { diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/AnnotationBasedArgumentConverter.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/AnnotationBasedArgumentConverter.java index 40dc578f40b4..9d2e2a275484 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/AnnotationBasedArgumentConverter.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/AnnotationBasedArgumentConverter.java @@ -10,7 +10,7 @@ package org.junit.jupiter.params.converter; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.annotation.Annotation; @@ -30,7 +30,7 @@ * @see AnnotationConsumer * @see SimpleArgumentConverter */ -@API(status = EXPERIMENTAL, since = "5.10") +@API(status = MAINTAINED, since = "5.13.3") public abstract class AnnotationBasedArgumentConverter implements ArgumentConverter, AnnotationConsumer { diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/ArgumentConverter.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/ArgumentConverter.java index 85a8e222b42c..056089bbdff0 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/ArgumentConverter.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/ArgumentConverter.java @@ -10,7 +10,7 @@ package org.junit.jupiter.params.converter; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; @@ -83,7 +83,7 @@ public interface ArgumentConverter { * conversion * @since 5.13 */ - @API(status = EXPERIMENTAL, since = "5.13") + @API(status = MAINTAINED, since = "5.13.3") default Object convert(Object source, FieldContext context) throws ArgumentConversionException { throw new JUnitException( String.format("ArgumentConverter does not override the convert(Object, FieldContext) method. " diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/JavaTimeConversionPattern.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/JavaTimeConversionPattern.java index c667722c6d8f..8559eebab160 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/JavaTimeConversionPattern.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/JavaTimeConversionPattern.java @@ -10,7 +10,7 @@ package org.junit.jupiter.params.converter; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; @@ -57,7 +57,7 @@ * * @since 5.12 */ - @API(status = EXPERIMENTAL, since = "5.12") + @API(status = MAINTAINED, since = "5.13.3") boolean nullable() default false; } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/AnnotationBasedArgumentsProvider.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/AnnotationBasedArgumentsProvider.java index 3abbbe760d15..307e2f4d930e 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/AnnotationBasedArgumentsProvider.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/AnnotationBasedArgumentsProvider.java @@ -11,7 +11,7 @@ package org.junit.jupiter.params.provider; import static org.apiguardian.api.API.Status.DEPRECATED; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.annotation.Annotation; import java.util.ArrayList; @@ -38,7 +38,7 @@ * @see org.junit.jupiter.params.provider.ArgumentsProvider * @see org.junit.jupiter.params.support.AnnotationConsumer */ -@API(status = EXPERIMENTAL, since = "5.10") +@API(status = MAINTAINED, since = "5.13.3") public abstract class AnnotationBasedArgumentsProvider implements ArgumentsProvider, AnnotationConsumer { diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/Arguments.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/Arguments.java index bb525eb94648..383c334906d2 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/Arguments.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/Arguments.java @@ -10,7 +10,7 @@ package org.junit.jupiter.params.provider; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; @@ -118,7 +118,7 @@ static Arguments arguments(Object... arguments) { * @see org.junit.jupiter.params.ParameterizedTest#ARGUMENT_SET_NAME_PLACEHOLDER * @see org.junit.jupiter.params.ParameterizedTest#ARGUMENT_SET_NAME_OR_ARGUMENTS_WITH_NAMES_PLACEHOLDER */ - @API(status = EXPERIMENTAL, since = "5.11") + @API(status = MAINTAINED, since = "5.13.3") static ArgumentSet argumentSet(String name, Object... arguments) { return new ArgumentSet(name, arguments); } @@ -132,7 +132,7 @@ static ArgumentSet argumentSet(String name, Object... arguments) { * @see org.junit.jupiter.params.ParameterizedTest#ARGUMENT_SET_NAME_PLACEHOLDER * @see org.junit.jupiter.params.ParameterizedTest#ARGUMENT_SET_NAME_OR_ARGUMENTS_WITH_NAMES_PLACEHOLDER */ - @API(status = EXPERIMENTAL, since = "5.11") + @API(status = MAINTAINED, since = "5.13.3") final class ArgumentSet implements Arguments { private final String name; diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/ArgumentsProvider.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/ArgumentsProvider.java index 058ab4803634..94eee0894cff 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/ArgumentsProvider.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/ArgumentsProvider.java @@ -11,7 +11,7 @@ package org.junit.jupiter.params.provider; import static org.apiguardian.api.API.Status.DEPRECATED; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import java.util.stream.Stream; @@ -72,7 +72,7 @@ default Stream provideArguments(@SuppressWarnings("unused") * @return a stream of arguments; never {@code null} * @since 5.13 */ - @API(status = EXPERIMENTAL, since = "5.13") + @API(status = MAINTAINED, since = "5.13.3") default Stream provideArguments(ParameterDeclarations parameters, ExtensionContext context) throws Exception { try { diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EnumSource.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EnumSource.java index a41b1af29455..000e3460f211 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EnumSource.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EnumSource.java @@ -11,7 +11,7 @@ package org.junit.jupiter.params.provider; import static java.util.stream.Collectors.toSet; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import java.lang.annotation.Documented; @@ -109,7 +109,7 @@ * * @since 5.12 */ - @API(status = EXPERIMENTAL, since = "5.12") + @API(status = MAINTAINED, since = "5.13.3") String from() default ""; /** @@ -125,7 +125,7 @@ * * @since 5.12 */ - @API(status = EXPERIMENTAL, since = "5.12") + @API(status = MAINTAINED, since = "5.13.3") String to() default ""; /** @@ -188,7 +188,7 @@ enum Mode { * @since 5.9 * @see java.util.stream.Stream#noneMatch(java.util.function.Predicate) */ - @API(status = EXPERIMENTAL, since = "5.9") + @API(status = MAINTAINED, since = "5.13.3") MATCH_NONE(Mode::validatePatterns, (name, patterns) -> patterns.stream().noneMatch(name::matches)); private final Validator validator; diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/FieldSource.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/FieldSource.java index 32666855bb9c..1b01d6c4de90 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/FieldSource.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/FieldSource.java @@ -10,7 +10,7 @@ package org.junit.jupiter.params.provider; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; @@ -134,7 +134,7 @@ @Documented @Inherited @Repeatable(FieldSources.class) -@API(status = EXPERIMENTAL, since = "5.11") +@API(status = MAINTAINED, since = "5.13.3") @ArgumentsSource(FieldArgumentsProvider.class) @SuppressWarnings("exports") public @interface FieldSource { diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/FieldSources.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/FieldSources.java index b49836cd2543..96f6b0f368dc 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/FieldSources.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/FieldSources.java @@ -10,7 +10,7 @@ package org.junit.jupiter.params.provider; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; @@ -41,7 +41,7 @@ @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited -@API(status = EXPERIMENTAL, since = "5.11") +@API(status = MAINTAINED, since = "5.13.3") public @interface FieldSources { /** diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/FieldContext.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/FieldContext.java index 355da13d126e..3cf0aeebb8e4 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/FieldContext.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/FieldContext.java @@ -10,7 +10,7 @@ package org.junit.jupiter.params.support; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.reflect.Field; @@ -28,7 +28,7 @@ * @see ParameterizedClass * @see Parameter */ -@API(status = EXPERIMENTAL, since = "5.13") +@API(status = MAINTAINED, since = "5.13.3") public interface FieldContext extends AnnotatedElementContext { /** diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/ParameterDeclaration.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/ParameterDeclaration.java index fca970de9df6..f3982ceaeb21 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/ParameterDeclaration.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/ParameterDeclaration.java @@ -10,7 +10,7 @@ package org.junit.jupiter.params.support; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.reflect.AnnotatedElement; import java.util.Optional; @@ -24,7 +24,7 @@ * @since 5.13 * @see ParameterDeclarations */ -@API(status = EXPERIMENTAL, since = "5.13") +@API(status = MAINTAINED, since = "5.13.3") public interface ParameterDeclaration { /** diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/ParameterDeclarations.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/ParameterDeclarations.java index bc30402ad63f..54772b0f6bff 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/ParameterDeclarations.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/ParameterDeclarations.java @@ -10,7 +10,7 @@ package org.junit.jupiter.params.support; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.reflect.AnnotatedElement; import java.util.List; @@ -40,7 +40,7 @@ * @see org.junit.jupiter.params.ParameterizedClass * @see org.junit.jupiter.params.ParameterizedTest */ -@API(status = EXPERIMENTAL, since = "5.13") +@API(status = MAINTAINED, since = "5.13.3") public interface ParameterDeclarations { /** diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/ParameterInfo.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/ParameterInfo.java index 03fd6b2a811d..ced3b899088c 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/ParameterInfo.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/ParameterInfo.java @@ -10,7 +10,7 @@ package org.junit.jupiter.params.support; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import org.apiguardian.api.API; import org.junit.jupiter.api.Nested; @@ -49,7 +49,7 @@ * @see ParameterizedClass * @see ParameterizedTest */ -@API(status = EXPERIMENTAL, since = "5.13") +@API(status = MAINTAINED, since = "5.13.3") public interface ParameterInfo { /** diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/AnnotationSupport.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/AnnotationSupport.java index 1f30697db788..4d42b21996fb 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/AnnotationSupport.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/AnnotationSupport.java @@ -11,7 +11,6 @@ package org.junit.platform.commons.support; import static org.apiguardian.api.API.Status.DEPRECATED; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.annotation.Annotation; @@ -213,7 +212,7 @@ public static Optional findAnnotation(Class clazz, * @since 1.12 * @see #findAnnotation(AnnotatedElement, Class) */ - @API(status = EXPERIMENTAL, since = "1.12") + @API(status = MAINTAINED, since = "1.13.3") public static Optional findAnnotation(Class clazz, Class annotationType, List> enclosingInstanceTypes) { diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/ModifierSupport.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/ModifierSupport.java index e92289ecc05e..e14e6963ee2c 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/ModifierSupport.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/ModifierSupport.java @@ -10,7 +10,6 @@ package org.junit.platform.commons.support; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.reflect.Member; @@ -151,7 +150,7 @@ public static boolean isAbstract(Member member) { * @since 1.13 * @see java.lang.reflect.Modifier#isAbstract(int) */ - @API(status = EXPERIMENTAL, since = "1.13") + @API(status = MAINTAINED, since = "1.13.3") public static boolean isNotAbstract(Class clazz) { return ReflectionUtils.isNotAbstract(clazz); } @@ -164,7 +163,7 @@ public static boolean isNotAbstract(Class clazz) { * @since 1.13 * @see java.lang.reflect.Modifier#isAbstract(int) */ - @API(status = EXPERIMENTAL, since = "1.13") + @API(status = MAINTAINED, since = "1.13.3") public static boolean isNotAbstract(Member member) { return ReflectionUtils.isNotAbstract(member); } diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/ReflectionSupport.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/ReflectionSupport.java index 5f8d2cbeffc4..e29592330693 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/ReflectionSupport.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/ReflectionSupport.java @@ -11,7 +11,6 @@ package org.junit.platform.commons.support; import static org.apiguardian.api.API.Status.DEPRECATED; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.reflect.Field; @@ -110,7 +109,7 @@ public static Try> tryToLoadClass(String name) { * @since 1.10 * @see #tryToLoadClass(String) */ - @API(status = EXPERIMENTAL, since = "1.10") + @API(status = MAINTAINED, since = "1.13.3") public static Try> tryToLoadClass(String name, ClassLoader classLoader) { return ReflectionUtils.tryToLoadClass(name, classLoader); } @@ -133,7 +132,7 @@ public static Try> tryToLoadClass(String name, ClassLoader classLoader) * @since 1.12 * @see #tryToGetResources(String, ClassLoader) */ - @API(status = EXPERIMENTAL, since = "1.12") + @API(status = MAINTAINED, since = "1.13.3") public static Try> tryToGetResources(String classpathResourceName) { return ReflectionUtils.tryToGetResources(classpathResourceName); } @@ -157,7 +156,7 @@ public static Try> tryToGetResources(String classpathResourceName) * @since 1.12 * @see #tryToGetResources(String) */ - @API(status = EXPERIMENTAL, since = "1.12") + @API(status = MAINTAINED, since = "1.13.3") public static Try> tryToGetResources(String classpathResourceName, ClassLoader classLoader) { return ReflectionUtils.tryToGetResources(classpathResourceName, classLoader); } @@ -201,7 +200,7 @@ public static List> findAllClassesInClasspathRoot(URI root, Predicate findAllResourcesInClasspathRoot(URI root, Predicate resourceFilter) { return ReflectionUtils.findAllResourcesInClasspathRoot(root, resourceFilter); } @@ -247,7 +246,7 @@ public static Stream> streamAllClassesInClasspathRoot(URI root, Predica * @see #streamAllResourcesInPackage(String, Predicate) * @see #streamAllResourcesInModule(String, Predicate) */ - @API(status = EXPERIMENTAL, since = "1.11") + @API(status = MAINTAINED, since = "1.13.3") public static Stream streamAllResourcesInClasspathRoot(URI root, Predicate resourceFilter) { return ReflectionUtils.streamAllResourcesInClasspathRoot(root, resourceFilter); } @@ -294,7 +293,7 @@ public static List> findAllClassesInPackage(String basePackageName, Pre * @see #findAllResourcesInClasspathRoot(URI, Predicate) * @see #findAllResourcesInModule(String, Predicate) */ - @API(status = EXPERIMENTAL, since = "1.11") + @API(status = MAINTAINED, since = "1.13.3") public static List findAllResourcesInPackage(String basePackageName, Predicate resourceFilter) { return ReflectionUtils.findAllResourcesInPackage(basePackageName, resourceFilter); } @@ -344,7 +343,7 @@ public static Stream> streamAllClassesInPackage(String basePackageName, * @see #streamAllResourcesInClasspathRoot(URI, Predicate) * @see #streamAllResourcesInModule(String, Predicate) */ - @API(status = EXPERIMENTAL, since = "1.11") + @API(status = MAINTAINED, since = "1.13.3") public static Stream streamAllResourcesInPackage(String basePackageName, Predicate resourceFilter) { @@ -392,7 +391,7 @@ public static List> findAllClassesInModule(String moduleName, Predicate * @see #findAllResourcesInClasspathRoot(URI, Predicate) * @see #findAllResourcesInPackage(String, Predicate) */ - @API(status = EXPERIMENTAL, since = "1.11") + @API(status = MAINTAINED, since = "1.13.3") public static List findAllResourcesInModule(String moduleName, Predicate resourceFilter) { return ReflectionUtils.findAllResourcesInModule(moduleName, resourceFilter); } @@ -438,7 +437,7 @@ public static Stream> streamAllClassesInModule(String moduleName, Predi * @see #streamAllResourcesInClasspathRoot(URI, Predicate) * @see #streamAllResourcesInPackage(String, Predicate) */ - @API(status = EXPERIMENTAL, since = "1.11") + @API(status = MAINTAINED, since = "1.13.3") public static Stream streamAllResourcesInModule(String moduleName, Predicate resourceFilter) { return ReflectionUtils.streamAllResourcesInModule(moduleName, resourceFilter); } @@ -712,7 +711,7 @@ public static Stream> streamNestedClasses(Class clazz, Predicate stringToObjectConverters = unmodifiableList(asList( // diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/ClassFilter.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/ClassFilter.java index c8bc48b6b0a4..8c4502d4814d 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/ClassFilter.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/ClassFilter.java @@ -10,7 +10,7 @@ package org.junit.platform.commons.support.scanning; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import java.util.function.Predicate; @@ -22,7 +22,7 @@ * * @since 1.1 */ -@API(status = EXPERIMENTAL, since = "1.12") +@API(status = MAINTAINED, since = "1.13.3") public class ClassFilter { /** diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/ClasspathScanner.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/ClasspathScanner.java index 344863ad6dac..348932108c4f 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/ClasspathScanner.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/ClasspathScanner.java @@ -28,7 +28,7 @@ * * @since 1.12 */ -@API(status = Status.EXPERIMENTAL, since = "1.12") +@API(status = Status.MAINTAINED, since = "1.13.3") public interface ClasspathScanner { /** diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/KotlinReflectionUtils.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/KotlinReflectionUtils.java new file mode 100644 index 000000000000..b94f547ebf6b --- /dev/null +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/KotlinReflectionUtils.java @@ -0,0 +1,99 @@ +/* + * Copyright 2015-2025 the original author or authors. + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v2.0 which + * accompanies this distribution and is available at + * + * https://www.eclipse.org/legal/epl-v20.html + */ + +package org.junit.platform.commons.util; + +import static org.apiguardian.api.API.Status.INTERNAL; +import static org.junit.platform.commons.util.ReflectionUtils.EMPTY_CLASS_ARRAY; +import static org.junit.platform.commons.util.ReflectionUtils.findMethod; +import static org.junit.platform.commons.util.ReflectionUtils.isStatic; +import static org.junit.platform.commons.util.ReflectionUtils.tryToLoadClass; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.util.Arrays; + +import org.apiguardian.api.API; +import org.junit.platform.commons.function.Try; + +/** + * Internal Kotlin-specific reflection utilities + * + * @since 5.13.3 + */ +@API(status = INTERNAL, since = "5.13.3") +public class KotlinReflectionUtils { + + private static final String DEFAULT_IMPLS_CLASS_NAME = "DefaultImpls"; + + private static final Class kotlinMetadata; + + static { + Try> metadata = tryToLoadKotlinMetadataClass(); + kotlinMetadata = metadata.toOptional().orElse(null); + } + + @SuppressWarnings("unchecked") + private static Try> tryToLoadKotlinMetadataClass() { + return tryToLoadClass("kotlin.Metadata") // + .andThenTry(it -> (Class) it); + } + + /** + * Determines whether the supplied class is a {@code DefaultImpls} class + * generated by the Kotlin compiler. + * + *

See + * Kotlin documentation + * for details. + * + * @since 5.13.3 + */ + @API(status = INTERNAL, since = "5.13.3") + public static boolean isKotlinInterfaceDefaultImplsClass(Class clazz) { + if (!isKotlinType(clazz) || !DEFAULT_IMPLS_CLASS_NAME.equals(clazz.getSimpleName()) || !isStatic(clazz)) { + return false; + } + + Class enclosingClass = clazz.getEnclosingClass(); + if (enclosingClass != null && enclosingClass.isInterface()) { + return Arrays.stream(clazz.getDeclaredMethods()) // + .anyMatch(method -> isCompilerGeneratedDefaultMethod(method, enclosingClass)); + } + + return false; + } + + private static boolean isCompilerGeneratedDefaultMethod(Method method, Class enclosingClass) { + if (isStatic(method) && method.getParameterCount() > 0) { + Class[] parameterTypes = method.getParameterTypes(); + if (parameterTypes[0] == enclosingClass) { + Class[] originalParameterTypes = copyWithoutFirst(parameterTypes); + return findMethod(enclosingClass, method.getName(), originalParameterTypes).isPresent(); + } + } + return false; + } + + private static Class[] copyWithoutFirst(Class[] values) { + if (values.length == 1) { + return EMPTY_CLASS_ARRAY; + } + Class[] result = new Class[values.length - 1]; + System.arraycopy(values, 1, result, 0, result.length); + return result; + } + + private static boolean isKotlinType(Class clazz) { + return kotlinMetadata != null // + && clazz.getDeclaredAnnotation(kotlinMetadata) != null; + } + +} diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ReflectionUtils.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ReflectionUtils.java index 7b044fe83249..11140fadce9a 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ReflectionUtils.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ReflectionUtils.java @@ -136,7 +136,7 @@ public enum HierarchyTraversalMode { // ++ => possessive quantifier private static final Pattern SOURCE_CODE_SYNTAX_ARRAY_PATTERN = Pattern.compile("^([^\\[\\]]+)((?>\\[\\])++)$"); - private static final Class[] EMPTY_CLASS_ARRAY = new Class[0]; + static final Class[] EMPTY_CLASS_ARRAY = new Class[0]; private static final ClasspathScanner classpathScanner = ClasspathScannerLoader.getInstance(); diff --git a/junit-platform-commons/src/testFixtures/java/org/junit/platform/commons/test/IdeUtils.java b/junit-platform-commons/src/testFixtures/java/org/junit/platform/commons/test/IdeUtils.java new file mode 100644 index 000000000000..1b20c64c8113 --- /dev/null +++ b/junit-platform-commons/src/testFixtures/java/org/junit/platform/commons/test/IdeUtils.java @@ -0,0 +1,27 @@ +/* + * Copyright 2015-2025 the original author or authors. + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v2.0 which + * accompanies this distribution and is available at + * + * https://www.eclipse.org/legal/epl-v20.html + */ + +package org.junit.platform.commons.test; + +/** + * Collection of test utilities for IDEs. + */ +public class IdeUtils { + + /** + * Determine if the current code is running in the Eclipse IDE. + *

Copied from {@code org.springframework.core.testfixture.ide.IdeUtils}. + */ + public static boolean runningInEclipse() { + return StackWalker.getInstance().walk( + stream -> stream.anyMatch(stackFrame -> stackFrame.getClassName().startsWith("org.eclipse.jdt"))); + } + +} diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/DiscoveryIssue.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/DiscoveryIssue.java index 287523181921..1177364fc375 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/DiscoveryIssue.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/DiscoveryIssue.java @@ -10,7 +10,7 @@ package org.junit.platform.engine; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import java.util.Optional; import java.util.function.UnaryOperator; @@ -24,7 +24,7 @@ * * @since 1.13 */ -@API(status = EXPERIMENTAL, since = "1.13") +@API(status = MAINTAINED, since = "1.13.3") public interface DiscoveryIssue { /** diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/DiscoverySelector.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/DiscoverySelector.java index 5284d19ee03e..35b0a5919df6 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/DiscoverySelector.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/DiscoverySelector.java @@ -10,7 +10,7 @@ package org.junit.platform.engine; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import java.util.Optional; @@ -45,7 +45,7 @@ public interface DiscoverySelector { * identifiers * @since 1.11 */ - @API(status = EXPERIMENTAL, since = "1.11") + @API(status = MAINTAINED, since = "1.13.3") default Optional toIdentifier() { return Optional.empty(); } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/DiscoverySelectorIdentifier.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/DiscoverySelectorIdentifier.java index 0a24baa5f0fe..bb7283175869 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/DiscoverySelectorIdentifier.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/DiscoverySelectorIdentifier.java @@ -10,7 +10,7 @@ package org.junit.platform.engine; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import java.util.Objects; @@ -29,7 +29,7 @@ * @see org.junit.platform.engine.discovery.DiscoverySelectors#parse(String) * @see org.junit.platform.engine.discovery.DiscoverySelectorIdentifierParser */ -@API(status = EXPERIMENTAL, since = "1.11") +@API(status = MAINTAINED, since = "1.13.3") public final class DiscoverySelectorIdentifier { private final String prefix; diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/EngineDiscoveryListener.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/EngineDiscoveryListener.java index 5fad4a0b5dd3..9bef80a16a21 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/EngineDiscoveryListener.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/EngineDiscoveryListener.java @@ -10,7 +10,7 @@ package org.junit.platform.engine; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; @@ -63,7 +63,7 @@ default void selectorProcessed(UniqueId engineId, DiscoverySelector selector, Se * @since 1.13 * @see DiscoveryIssue */ - @API(status = EXPERIMENTAL, since = "1.13") + @API(status = MAINTAINED, since = "1.13.3") default void issueEncountered(UniqueId engineId, DiscoveryIssue issue) { } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/EngineDiscoveryRequest.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/EngineDiscoveryRequest.java index 3bdacace4401..14ff5386a9be 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/EngineDiscoveryRequest.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/EngineDiscoveryRequest.java @@ -10,7 +10,7 @@ package org.junit.platform.engine; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import java.util.List; @@ -89,7 +89,7 @@ default EngineDiscoveryListener getDiscoveryListener() { * @return the output directory provider; never {@code null} * @since 1.12 */ - @API(status = EXPERIMENTAL, since = "1.12") + @API(status = MAINTAINED, since = "1.13.3") default OutputDirectoryProvider getOutputDirectoryProvider() { throw new JUnitException( "OutputDirectoryProvider not available; probably due to unaligned versions of the junit-platform-engine and junit-platform-launcher jars on the classpath/module path."); diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/EngineExecutionListener.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/EngineExecutionListener.java index 8affe7aad78c..8c764d120b19 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/EngineExecutionListener.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/EngineExecutionListener.java @@ -10,7 +10,7 @@ package org.junit.platform.engine; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; @@ -156,7 +156,7 @@ default void reportingEntryPublished(TestDescriptor testDescriptor, ReportEntry * the file entry belongs * @param file a {@code FileEntry} instance to be attached */ - @API(status = EXPERIMENTAL, since = "1.12") + @API(status = MAINTAINED, since = "1.13.3") default void fileEntryPublished(TestDescriptor testDescriptor, FileEntry file) { } } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/ExecutionRequest.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/ExecutionRequest.java index 1267551da486..2024aa0d318e 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/ExecutionRequest.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/ExecutionRequest.java @@ -11,8 +11,8 @@ package org.junit.platform.engine; import static org.apiguardian.api.API.Status.DEPRECATED; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.INTERNAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; @@ -144,7 +144,7 @@ public ConfigurationParameters getConfigurationParameters() { * is not available * @since 1.12 */ - @API(status = EXPERIMENTAL, since = "1.12") + @API(status = MAINTAINED, since = "1.13.3") public OutputDirectoryProvider getOutputDirectoryProvider() { return Preconditions.notNull(this.outputDirectoryProvider, "No OutputDirectoryProvider was configured for this request"); @@ -161,7 +161,7 @@ public OutputDirectoryProvider getOutputDirectoryProvider() { * @since 1.13 * @see NamespacedHierarchicalStore */ - @API(status = EXPERIMENTAL, since = "1.13") + @API(status = MAINTAINED, since = "1.13.3") public NamespacedHierarchicalStore getStore() { return Preconditions.notNull(this.requestLevelStore, "No NamespacedHierarchicalStore was configured for this request"); diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/TestDescriptor.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/TestDescriptor.java index b23d2d79ed09..b04f0ceead20 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/TestDescriptor.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/TestDescriptor.java @@ -10,7 +10,7 @@ package org.junit.platform.engine; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import java.util.ArrayList; @@ -188,7 +188,7 @@ default Set getDescendants() { * @param orderer a unary operator to order the children of this test descriptor * @since 1.12 */ - @API(since = "1.12", status = EXPERIMENTAL) + @API(status = MAINTAINED, since = "1.13.3") default void orderChildren(UnaryOperator> orderer) { Preconditions.notNull(orderer, "orderer must not be null"); Set originalChildren = getChildren(); @@ -333,7 +333,7 @@ interface Visitor { * is empty * @since 1.13 */ - @API(status = EXPERIMENTAL, since = "1.13") + @API(status = MAINTAINED, since = "1.13.3") static Visitor composite(Visitor... visitors) { return CompositeTestDescriptorVisitor.from(visitors); } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/ClassSelector.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/ClassSelector.java index 38c412c1e5c1..9eb8da9e11d9 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/ClassSelector.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/ClassSelector.java @@ -10,8 +10,8 @@ package org.junit.platform.engine.discovery; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.INTERNAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import java.util.Objects; @@ -69,7 +69,7 @@ public class ClassSelector implements DiscoverySelector { * @return the {@code ClassLoader}; potentially {@code null} * @since 1.10 */ - @API(status = EXPERIMENTAL, since = "1.10") + @API(status = MAINTAINED, since = "1.13.3") public ClassLoader getClassLoader() { return this.classLoader; } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/ClasspathResourceSelector.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/ClasspathResourceSelector.java index d703b5da7d2b..3f7f8d66d395 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/ClasspathResourceSelector.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/ClasspathResourceSelector.java @@ -11,8 +11,8 @@ package org.junit.platform.engine.discovery; import static java.util.Collections.unmodifiableSet; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.INTERNAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import java.util.LinkedHashSet; @@ -93,7 +93,7 @@ public String getClasspathResourceName() { * * @since 1.12 */ - @API(status = EXPERIMENTAL, since = "1.12") + @API(status = MAINTAINED, since = "1.13.3") public Set getClasspathResources() { if (this.classpathResources == null) { Try> tryToGetResource = ReflectionUtils.tryToGetResources(this.classpathResourceName); diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/DiscoverySelectorIdentifierParser.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/DiscoverySelectorIdentifierParser.java index a643a21d89fc..857d5c2835a9 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/DiscoverySelectorIdentifierParser.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/DiscoverySelectorIdentifierParser.java @@ -10,7 +10,7 @@ package org.junit.platform.engine.discovery; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import java.util.Optional; @@ -28,7 +28,7 @@ * @since 1.11 * @see DiscoverySelectors#parse(String) */ -@API(status = EXPERIMENTAL, since = "1.11") +@API(status = MAINTAINED, since = "1.13.3") public interface DiscoverySelectorIdentifierParser { /** diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/DiscoverySelectors.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/DiscoverySelectors.java index 299204c35677..ee766a534348 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/DiscoverySelectors.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/DiscoverySelectors.java @@ -11,7 +11,7 @@ package org.junit.platform.engine.discovery; import static java.util.stream.Collectors.toList; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import static org.junit.platform.commons.util.CollectionUtils.toUnmodifiableList; @@ -349,7 +349,7 @@ public static ClasspathResourceSelector selectClasspathResource(String classpath * @see ClasspathResourceSelector * @see ReflectionSupport#tryToGetResources(String) */ - @API(status = EXPERIMENTAL, since = "1.12") + @API(status = MAINTAINED, since = "1.13.3") public static ClasspathResourceSelector selectClasspathResource(Set classpathResources) { Preconditions.notEmpty(classpathResources, "classpath resources must not be null or empty"); Preconditions.containsNoNullElements(classpathResources, "individual classpath resources must not be null"); @@ -445,7 +445,7 @@ public static ClassSelector selectClass(String className) { * @since 1.10 * @see ClassSelector */ - @API(status = EXPERIMENTAL, since = "1.10") + @API(status = MAINTAINED, since = "1.13.3") public static ClassSelector selectClass(ClassLoader classLoader, String className) { Preconditions.notBlank(className, "Class name must not be null or blank"); return new ClassSelector(classLoader, className); @@ -513,7 +513,7 @@ public static MethodSelector selectMethod(String fullyQualifiedMethodName) throw * @see #selectMethod(String) * @see MethodSelector */ - @API(status = EXPERIMENTAL, since = "1.10") + @API(status = MAINTAINED, since = "1.13.3") public static MethodSelector selectMethod(ClassLoader classLoader, String fullyQualifiedMethodName) throws PreconditionViolationException { String[] methodParts = ReflectionUtils.parseFullyQualifiedMethodName(fullyQualifiedMethodName); @@ -545,7 +545,7 @@ public static MethodSelector selectMethod(String className, String methodName) { * @since 1.10 * @see MethodSelector */ - @API(status = EXPERIMENTAL, since = "1.10") + @API(status = MAINTAINED, since = "1.13.3") public static MethodSelector selectMethod(ClassLoader classLoader, String className, String methodName) { return selectMethod(classLoader, className, methodName, ""); } @@ -589,7 +589,7 @@ public static MethodSelector selectMethod(String className, String methodName, S * @since 1.10 * @see MethodSelector */ - @API(status = EXPERIMENTAL, since = "1.10") + @API(status = MAINTAINED, since = "1.13.3") public static MethodSelector selectMethod(ClassLoader classLoader, String className, String methodName, String parameterTypeNames) { Preconditions.notBlank(className, "Class name must not be null or blank"); @@ -645,7 +645,7 @@ public static MethodSelector selectMethod(Class javaClass, String methodName, * @since 1.10 * @see MethodSelector */ - @API(status = EXPERIMENTAL, since = "1.10") + @API(status = MAINTAINED, since = "1.13.3") public static MethodSelector selectMethod(String className, String methodName, Class... parameterTypes) { Preconditions.notBlank(className, "Class name must not be null or blank"); Preconditions.notBlank(methodName, "Method name must not be null or blank"); @@ -666,7 +666,7 @@ public static MethodSelector selectMethod(String className, String methodName, C * @since 1.10 * @see MethodSelector */ - @API(status = EXPERIMENTAL, since = "1.10") + @API(status = MAINTAINED, since = "1.13.3") public static MethodSelector selectMethod(Class javaClass, String methodName, Class... parameterTypes) { Preconditions.notNull(javaClass, "Class must not be null"); Preconditions.notBlank(methodName, "Method name must not be null or blank"); @@ -730,7 +730,7 @@ public static NestedClassSelector selectNestedClass(List enclosingClassN * @since 1.10 * @see NestedClassSelector */ - @API(status = EXPERIMENTAL, since = "1.10") + @API(status = MAINTAINED, since = "1.13.3") public static NestedClassSelector selectNestedClass(ClassLoader classLoader, List enclosingClassNames, String nestedClassName) { Preconditions.notEmpty(enclosingClassNames, "Enclosing class names must not be null or empty"); @@ -766,7 +766,7 @@ public static NestedMethodSelector selectNestedMethod(List enclosingClas * @since 1.10 * @see NestedMethodSelector */ - @API(status = EXPERIMENTAL, since = "1.10") + @API(status = MAINTAINED, since = "1.13.3") public static NestedMethodSelector selectNestedMethod(ClassLoader classLoader, List enclosingClassNames, String nestedClassName, String methodName) throws PreconditionViolationException { Preconditions.notEmpty(enclosingClassNames, "Enclosing class names must not be null or empty"); @@ -814,7 +814,7 @@ public static NestedMethodSelector selectNestedMethod(List enclosingClas * @since 1.10 * @see #selectNestedMethod(List, String, String, String) */ - @API(status = EXPERIMENTAL, since = "1.10") + @API(status = MAINTAINED, since = "1.13.3") public static NestedMethodSelector selectNestedMethod(ClassLoader classLoader, List enclosingClassNames, String nestedClassName, String methodName, String parameterTypeNames) { @@ -840,7 +840,7 @@ public static NestedMethodSelector selectNestedMethod(ClassLoader classLoader, L * @since 1.10 * @see NestedMethodSelector */ - @API(status = EXPERIMENTAL, since = "1.10") + @API(status = MAINTAINED, since = "1.13.3") public static NestedMethodSelector selectNestedMethod(List enclosingClassNames, String nestedClassName, String methodName, Class... parameterTypes) { @@ -909,7 +909,7 @@ public static NestedMethodSelector selectNestedMethod(List> enclosingCl * @since 1.10 * @see NestedMethodSelector */ - @API(status = EXPERIMENTAL, since = "1.10") + @API(status = MAINTAINED, since = "1.13.3") public static NestedMethodSelector selectNestedMethod(List> enclosingClasses, Class nestedClass, String methodName, Class... parameterTypes) { @@ -973,7 +973,7 @@ public static UniqueIdSelector selectUniqueId(String uniqueId) { * @since 1.9 * @see IterationSelector */ - @API(status = EXPERIMENTAL, since = "1.9") + @API(status = MAINTAINED, since = "1.13.3") public static IterationSelector selectIteration(DiscoverySelector parentSelector, int... iterationIndices) { Preconditions.notNull(parentSelector, "Parent selector must not be null"); Preconditions.notEmpty(iterationIndices, "iteration indices must not be empty"); @@ -990,7 +990,7 @@ public static IterationSelector selectIteration(DiscoverySelector parentSelector * @since 1.11 * @see DiscoverySelectorIdentifierParser */ - @API(status = EXPERIMENTAL, since = "1.11") + @API(status = MAINTAINED, since = "1.13.3") public static Optional parse(String identifier) { return DiscoverySelectorIdentifierParsers.parse(identifier); } @@ -1005,7 +1005,7 @@ public static Optional parse(String identifier) { * @since 1.11 * @see DiscoverySelectorIdentifierParser */ - @API(status = EXPERIMENTAL, since = "1.11") + @API(status = MAINTAINED, since = "1.13.3") public static Optional parse(DiscoverySelectorIdentifier identifier) { return DiscoverySelectorIdentifierParsers.parse(identifier); } @@ -1021,7 +1021,7 @@ public static Optional parse(DiscoverySelectorIdent * @since 1.11 * @see DiscoverySelectorIdentifierParser */ - @API(status = EXPERIMENTAL, since = "1.11") + @API(status = MAINTAINED, since = "1.13.3") public static Stream parseAll(String... identifiers) { return DiscoverySelectorIdentifierParsers.parseAll(identifiers); } @@ -1037,7 +1037,7 @@ public static Stream parseAll(String... identifiers * @since 1.11 * @see DiscoverySelectorIdentifierParser */ - @API(status = EXPERIMENTAL, since = "1.11") + @API(status = MAINTAINED, since = "1.13.3") public static Stream parseAll(Collection identifiers) { return DiscoverySelectorIdentifierParsers.parseAll(identifiers); } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/IterationSelector.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/IterationSelector.java index dd603097263b..01b4fa5b1cf7 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/IterationSelector.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/IterationSelector.java @@ -13,8 +13,8 @@ import static java.util.stream.Collectors.collectingAndThen; import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.toCollection; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.INTERNAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import java.util.ArrayList; import java.util.Arrays; @@ -44,7 +44,7 @@ * @since 1.9 * @see DiscoverySelectors#selectIteration(DiscoverySelector, int...) */ -@API(status = EXPERIMENTAL, since = "1.9") +@API(status = MAINTAINED, since = "1.13.3") public class IterationSelector implements DiscoverySelector { private final DiscoverySelector parentSelector; diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/MethodSelector.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/MethodSelector.java index 2bbe3ca08411..7e16ed851535 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/MethodSelector.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/MethodSelector.java @@ -11,8 +11,8 @@ package org.junit.platform.engine.discovery; import static org.apiguardian.api.API.Status.DEPRECATED; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.INTERNAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import java.lang.reflect.Method; @@ -126,7 +126,7 @@ public class MethodSelector implements DiscoverySelector { * @return the {@code ClassLoader}; potentially {@code null} * @since 1.10 */ - @API(status = EXPERIMENTAL, since = "1.10") + @API(status = MAINTAINED, since = "1.13.3") public ClassLoader getClassLoader() { return this.classLoader; } @@ -227,7 +227,7 @@ public Method getJavaMethod() { * @see #getParameterTypeNames() * @see Method#getParameterTypes() */ - @API(status = EXPERIMENTAL, since = "1.10") + @API(status = MAINTAINED, since = "1.13.3") public Class[] getParameterTypes() { lazyLoadParameterTypes(); return this.parameterTypes.clone(); diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/NestedClassSelector.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/NestedClassSelector.java index c61f68d6df18..0b234a7e14ca 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/NestedClassSelector.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/NestedClassSelector.java @@ -12,8 +12,8 @@ import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.toList; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.INTERNAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import static org.junit.platform.commons.util.CollectionUtils.toUnmodifiableList; @@ -78,7 +78,7 @@ public class NestedClassSelector implements DiscoverySelector { * @return the {@code ClassLoader}; potentially {@code null} * @since 1.10 */ - @API(status = EXPERIMENTAL, since = "1.10") + @API(status = MAINTAINED, since = "1.13.3") public ClassLoader getClassLoader() { return this.classLoader; } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/NestedMethodSelector.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/NestedMethodSelector.java index 25f17d67ca92..2fd643386b13 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/NestedMethodSelector.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/NestedMethodSelector.java @@ -11,8 +11,8 @@ package org.junit.platform.engine.discovery; import static org.apiguardian.api.API.Status.DEPRECATED; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.INTERNAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import java.lang.reflect.Method; @@ -101,7 +101,7 @@ public class NestedMethodSelector implements DiscoverySelector { * * @since 1.10 */ - @API(status = EXPERIMENTAL, since = "1.10") + @API(status = MAINTAINED, since = "1.13.3") public ClassLoader getClassLoader() { return this.nestedClassSelector.getClassLoader(); } @@ -209,7 +209,7 @@ public String getParameterTypeNames() { * @see #getParameterTypeNames() * @see MethodSelector#getParameterTypes() */ - @API(status = EXPERIMENTAL, since = "1.10") + @API(status = MAINTAINED, since = "1.13.3") public Class[] getParameterTypes() { return this.methodSelector.getParameterTypes(); } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/reporting/FileEntry.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/reporting/FileEntry.java index 13ad5f022b52..1e9f1ac82beb 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/reporting/FileEntry.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/reporting/FileEntry.java @@ -10,7 +10,7 @@ package org.junit.platform.engine.reporting; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import java.nio.file.Path; import java.time.LocalDateTime; @@ -27,7 +27,7 @@ * @since 1.12 * @see #from(Path, String) */ -@API(status = EXPERIMENTAL, since = "1.12") +@API(status = MAINTAINED, since = "1.13.3") public final class FileEntry { /** diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/reporting/OutputDirectoryProvider.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/reporting/OutputDirectoryProvider.java index 60fc831b9822..c1e55406c456 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/reporting/OutputDirectoryProvider.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/reporting/OutputDirectoryProvider.java @@ -10,7 +10,7 @@ package org.junit.platform.engine.reporting; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import java.io.IOException; import java.nio.file.Path; @@ -26,7 +26,7 @@ * @since 1.12 * @see EngineDiscoveryRequest#getOutputDirectoryProvider() */ -@API(status = EXPERIMENTAL, since = "1.12") +@API(status = MAINTAINED, since = "1.13.3") public interface OutputDirectoryProvider { /** diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/discovery/DiscoveryIssueReporter.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/discovery/DiscoveryIssueReporter.java index 8226df455562..469563eea621 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/discovery/DiscoveryIssueReporter.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/discovery/DiscoveryIssueReporter.java @@ -10,7 +10,7 @@ package org.junit.platform.engine.support.discovery; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import java.util.Collection; import java.util.HashSet; @@ -34,7 +34,7 @@ * @since 1.13 * @see SelectorResolver.Context */ -@API(status = EXPERIMENTAL, since = "1.13") +@API(status = MAINTAINED, since = "1.13.3") public interface DiscoveryIssueReporter { /** diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/discovery/EngineDiscoveryRequestResolver.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/discovery/EngineDiscoveryRequestResolver.java index 4c5dbf3037d9..bbc3c76cb2fc 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/discovery/EngineDiscoveryRequestResolver.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/discovery/EngineDiscoveryRequestResolver.java @@ -11,7 +11,7 @@ package org.junit.platform.engine.support.discovery; import static java.util.stream.Collectors.toCollection; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import java.util.ArrayList; @@ -136,7 +136,7 @@ public void resolve(EngineDiscoveryRequest request, T engineDescriptor) { * @see SelectorResolver * @see TestDescriptor.Visitor */ - @API(status = EXPERIMENTAL, since = "1.13") + @API(status = MAINTAINED, since = "1.13.3") public void resolve(EngineDiscoveryRequest request, T engineDescriptor, DiscoveryIssueReporter issueReporter) { Preconditions.notNull(request, "request must not be null"); Preconditions.notNull(engineDescriptor, "engineDescriptor must not be null"); @@ -207,7 +207,7 @@ public Builder addClassContainerSelectorResolver(Predicate> classFil * {@code null} * @return this builder for method chaining */ - @API(status = EXPERIMENTAL, since = "1.13") + @API(status = MAINTAINED, since = "1.13.3") public Builder addClassContainerSelectorResolverWithContext( Function, Predicate>> classFilterCreator) { Preconditions.notNull(classFilterCreator, "classFilterCreator must not be null"); @@ -227,7 +227,7 @@ public Builder addClassContainerSelectorResolverWithContext( * @return this builder for method chaining * @since 1.12 */ - @API(status = EXPERIMENTAL, since = "1.12") + @API(status = MAINTAINED, since = "1.13.3") public Builder addResourceContainerSelectorResolver(Predicate resourceFilter) { Preconditions.notNull(resourceFilter, "resourceFilter must not be null"); return addSelectorResolver( @@ -336,7 +336,7 @@ public interface InitializationContext { * {@code null} * @since 1.12 */ - @API(status = EXPERIMENTAL, since = "1.12") + @API(status = MAINTAINED, since = "1.13.3") Predicate getPackageFilter(); /** @@ -345,7 +345,7 @@ public interface InitializationContext { * * @since 1.13 */ - @API(status = EXPERIMENTAL, since = "1.13") + @API(status = MAINTAINED, since = "1.13.3") DiscoveryIssueReporter getIssueReporter(); } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/discovery/SelectorResolver.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/discovery/SelectorResolver.java index a402a4679152..e507cf47fc10 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/discovery/SelectorResolver.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/discovery/SelectorResolver.java @@ -12,7 +12,7 @@ import static java.util.Collections.emptySet; import static java.util.Collections.singleton; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import java.util.Collections; @@ -315,7 +315,7 @@ default Resolution resolve(UriSelector selector, Context context) { * Resolution#matches(Set) matches()}; never {@code null} * @see #resolve(DiscoverySelector, Context) */ - @API(status = EXPERIMENTAL, since = "1.9") + @API(status = MAINTAINED, since = "1.13.3") default Resolution resolve(IterationSelector selector, Context context) { return resolve((DiscoverySelector) selector, context); } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/DefaultParallelExecutionConfigurationStrategy.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/DefaultParallelExecutionConfigurationStrategy.java index 304c9e943f58..86abea725dca 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/DefaultParallelExecutionConfigurationStrategy.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/DefaultParallelExecutionConfigurationStrategy.java @@ -10,7 +10,7 @@ package org.junit.platform.engine.support.hierarchical; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import java.math.BigDecimal; @@ -144,7 +144,7 @@ public ParallelExecutionConfiguration createConfiguration(ConfigurationParameter * @since 1.10 * @see #FIXED */ - @API(status = EXPERIMENTAL, since = "1.10") + @API(status = MAINTAINED, since = "1.13.3") public static final String CONFIG_FIXED_MAX_POOL_SIZE_PROPERTY_NAME = "fixed.max-pool-size"; /** @@ -160,7 +160,7 @@ public ParallelExecutionConfiguration createConfiguration(ConfigurationParameter * @see #FIXED * @see #CONFIG_FIXED_MAX_POOL_SIZE_PROPERTY_NAME */ - @API(status = EXPERIMENTAL, since = "1.10") + @API(status = MAINTAINED, since = "1.13.3") public static final String CONFIG_FIXED_SATURATE_PROPERTY_NAME = "fixed.saturate"; /** @@ -188,7 +188,7 @@ public ParallelExecutionConfiguration createConfiguration(ConfigurationParameter * @since 1.10 * @see #DYNAMIC */ - @API(status = EXPERIMENTAL, since = "1.10") + @API(status = MAINTAINED, since = "1.13.3") public static final String CONFIG_DYNAMIC_MAX_POOL_SIZE_FACTOR_PROPERTY_NAME = "dynamic.max-pool-size-factor"; /** @@ -204,7 +204,7 @@ public ParallelExecutionConfiguration createConfiguration(ConfigurationParameter * @see #DYNAMIC * @see #CONFIG_DYNAMIC_FACTOR_PROPERTY_NAME */ - @API(status = EXPERIMENTAL, since = "1.10") + @API(status = MAINTAINED, since = "1.13.3") public static final String CONFIG_DYNAMIC_SATURATE_PROPERTY_NAME = "dynamic.saturate"; /** diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/store/Namespace.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/store/Namespace.java index dcf06d571833..a22f9e461b03 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/store/Namespace.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/store/Namespace.java @@ -10,7 +10,7 @@ package org.junit.platform.engine.support.store; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import java.util.ArrayList; import java.util.Arrays; @@ -28,7 +28,7 @@ * mixing data between extensions or across different invocations within the * lifecycle of a single extension. */ -@API(status = EXPERIMENTAL, since = "1.13") +@API(status = MAINTAINED, since = "1.13.3") public class Namespace { /** diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/store/NamespacedHierarchicalStore.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/store/NamespacedHierarchicalStore.java index bd27996973b1..03db2ded51f7 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/store/NamespacedHierarchicalStore.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/store/NamespacedHierarchicalStore.java @@ -11,7 +11,7 @@ package org.junit.platform.engine.support.store; import static java.util.Comparator.comparing; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.junit.platform.commons.util.ReflectionUtils.getWrapperType; import static org.junit.platform.commons.util.ReflectionUtils.isAssignableTo; @@ -44,7 +44,7 @@ * @param Namespace type * @since 1.10 */ -@API(status = EXPERIMENTAL, since = "1.10") +@API(status = MAINTAINED, since = "1.13.3") public final class NamespacedHierarchicalStore implements AutoCloseable { private final AtomicInteger insertOrderSequence = new AtomicInteger(); @@ -94,7 +94,7 @@ public NamespacedHierarchicalStore newChild() { * @return an {@code Optional} containing the parent store, or an empty {@code Optional} if there is no parent * @since 5.13 */ - @API(status = EXPERIMENTAL, since = "5.13") + @API(status = MAINTAINED, since = "5.13.3") public Optional> getParent() { return Optional.ofNullable(this.parentStore); } @@ -106,7 +106,7 @@ public Optional> getParent() { * @since 1.11 * @see #close() */ - @API(status = EXPERIMENTAL, since = "1.11") + @API(status = MAINTAINED, since = "1.13.3") public boolean isClosed() { return this.closed; } @@ -461,7 +461,7 @@ public Failure(Throwable throwable) { @FunctionalInterface public interface CloseAction { - @API(status = EXPERIMENTAL, since = "1.13") + @API(status = MAINTAINED, since = "1.13.3") static CloseAction closeAutoCloseables() { return (__, ___, value) -> { if (value instanceof AutoCloseable) { diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/store/NamespacedHierarchicalStoreException.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/store/NamespacedHierarchicalStoreException.java index 2e67f3d203f4..0fdbf19cde10 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/store/NamespacedHierarchicalStoreException.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/store/NamespacedHierarchicalStoreException.java @@ -10,7 +10,7 @@ package org.junit.platform.engine.support.store; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; @@ -20,7 +20,7 @@ * * @since 1.10 */ -@API(status = EXPERIMENTAL, since = "1.10") +@API(status = MAINTAINED, since = "1.13.3") public class NamespacedHierarchicalStoreException extends JUnitException { private static final long serialVersionUID = 1L; diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/LauncherConstants.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/LauncherConstants.java index a18a71b45c74..e8ce4ee1c773 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/LauncherConstants.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/LauncherConstants.java @@ -10,7 +10,7 @@ package org.junit.platform.launcher; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; @@ -162,7 +162,7 @@ public class LauncherConstants { * * @see LauncherInterceptor */ - @API(status = EXPERIMENTAL, since = "1.10") + @API(status = MAINTAINED, since = "1.13.3") public static final String ENABLE_LAUNCHER_INTERCEPTORS = "junit.platform.launcher.interceptors.enabled"; /** @@ -178,7 +178,7 @@ public class LauncherConstants { * *

Value must be either {@code true} or {@code false}; defaults to {@code false}. */ - @API(status = EXPERIMENTAL, since = "1.10") + @API(status = MAINTAINED, since = "1.13.3") public static final String DRY_RUN_PROPERTY_NAME = "junit.platform.execution.dryRun.enabled"; /** @@ -188,7 +188,7 @@ public class LauncherConstants { * * @see org.junit.platform.launcher.core.EngineExecutionOrchestrator */ - @API(status = EXPERIMENTAL, since = "1.10") + @API(status = MAINTAINED, since = "1.13.3") public static final String STACKTRACE_PRUNING_ENABLED_PROPERTY_NAME = "junit.platform.stacktrace.pruning.enabled"; /** @@ -202,7 +202,7 @@ public class LauncherConstants { * @see #OUTPUT_DIR_UNIQUE_NUMBER_PLACEHOLDER * @see org.junit.platform.engine.reporting.OutputDirectoryProvider */ - @API(status = EXPERIMENTAL, since = "1.12") + @API(status = MAINTAINED, since = "1.13.3") public static final String OUTPUT_DIR_PROPERTY_NAME = "junit.platform.reporting.output.dir"; /** @@ -216,7 +216,7 @@ public class LauncherConstants { * @since 1.12 * @see #OUTPUT_DIR_PROPERTY_NAME */ - @API(status = EXPERIMENTAL, since = "1.12") + @API(status = MAINTAINED, since = "1.13.3") public static final String OUTPUT_DIR_UNIQUE_NUMBER_PLACEHOLDER = "{uniqueNumber}"; /** @@ -242,7 +242,7 @@ public class LauncherConstants { * @since 1.13 * @see org.junit.platform.engine.DiscoveryIssue.Severity */ - @API(status = EXPERIMENTAL, since = "1.13") + @API(status = MAINTAINED, since = "1.13.3") public static final String CRITICAL_DISCOVERY_ISSUE_SEVERITY_PROPERTY_NAME = "junit.platform.discovery.issue.severity.critical"; /** @@ -263,7 +263,7 @@ public class LauncherConstants { * @since 1.13 * @see #CRITICAL_DISCOVERY_ISSUE_SEVERITY_PROPERTY_NAME */ - @API(status = EXPERIMENTAL, since = "1.13") + @API(status = MAINTAINED, since = "1.13.3") public static final String DISCOVERY_ISSUE_FAILURE_PHASE_PROPERTY_NAME = "junit.platform.discovery.issue.failure.phase"; private LauncherConstants() { diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/LauncherInterceptor.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/LauncherInterceptor.java index 490ac65483a2..5bc798aceade 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/LauncherInterceptor.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/LauncherInterceptor.java @@ -10,7 +10,7 @@ package org.junit.platform.launcher; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import org.apiguardian.api.API; @@ -52,7 +52,7 @@ * @see LauncherSession * @see LauncherConstants#ENABLE_LAUNCHER_INTERCEPTORS */ -@API(status = EXPERIMENTAL, since = "1.10") +@API(status = MAINTAINED, since = "1.13.3") public interface LauncherInterceptor { /** diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/LauncherSession.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/LauncherSession.java index 285621b59812..9deea873387b 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/LauncherSession.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/LauncherSession.java @@ -10,7 +10,7 @@ package org.junit.platform.launcher; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; @@ -62,7 +62,7 @@ public interface LauncherSession extends AutoCloseable { * @since 1.13 * @see NamespacedHierarchicalStore */ - @API(status = EXPERIMENTAL, since = "1.13") + @API(status = MAINTAINED, since = "1.13.3") NamespacedHierarchicalStore getStore(); } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/MethodFilter.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/MethodFilter.java index cff14852ed79..91d1b1f0baae 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/MethodFilter.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/MethodFilter.java @@ -10,7 +10,7 @@ package org.junit.platform.launcher; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.reflect.Method; import java.util.List; @@ -25,7 +25,7 @@ * @see #includeMethodNamePatterns(String...) * @see #excludeMethodNamePatterns(String...) */ -@API(status = EXPERIMENTAL, since = "1.12") +@API(status = MAINTAINED, since = "1.13.3") public interface MethodFilter extends PostDiscoveryFilter { /** diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestExecutionListener.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestExecutionListener.java index 10f6327a4a76..016de421e3c1 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestExecutionListener.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestExecutionListener.java @@ -10,7 +10,7 @@ package org.junit.platform.launcher; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; @@ -195,7 +195,7 @@ default void reportingEntryPublished(TestIdentifier testIdentifier, ReportEntry * @param testIdentifier describes the test or container to which the entry pertains * @param file the published {@code FileEntry} */ - @API(status = EXPERIMENTAL, since = "1.12") + @API(status = MAINTAINED, since = "1.13.3") default void fileEntryPublished(TestIdentifier testIdentifier, FileEntry file) { } } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestPlan.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestPlan.java index 522c715a1efe..fc6d46b67973 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestPlan.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestPlan.java @@ -14,7 +14,6 @@ import static java.util.Collections.synchronizedSet; import static java.util.Collections.unmodifiableSet; import static org.apiguardian.api.API.Status.DEPRECATED; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.INTERNAL; import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; @@ -300,7 +299,7 @@ public ConfigurationParameters getConfigurationParameters() { * @return the output directory provider; never {@code null} * @since 1.12 */ - @API(status = EXPERIMENTAL, since = "1.12") + @API(status = MAINTAINED, since = "1.13.3") public OutputDirectoryProvider getOutputDirectoryProvider() { return this.outputDirectoryProvider; } @@ -312,7 +311,7 @@ public OutputDirectoryProvider getOutputDirectoryProvider() { * @param visitor the visitor to accept; never {@code null} * @since 1.10 */ - @API(status = EXPERIMENTAL, since = "1.10") + @API(status = MAINTAINED, since = "1.13.3") public void accept(Visitor visitor) { getRoots().forEach(it -> accept(visitor, it)); } @@ -333,7 +332,7 @@ private void accept(Visitor visitor, TestIdentifier testIdentifier) { * * @since 1.10 */ - @API(status = EXPERIMENTAL, since = "1.10") + @API(status = MAINTAINED, since = "1.13.3") public interface Visitor { /** diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DiscoveryIssueException.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DiscoveryIssueException.java index 563e3a33629b..fdfb62e630af 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DiscoveryIssueException.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DiscoveryIssueException.java @@ -10,7 +10,7 @@ package org.junit.platform.launcher.core; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; @@ -21,7 +21,7 @@ * * @since 1.13 */ -@API(status = EXPERIMENTAL, since = "1.13") +@API(status = MAINTAINED, since = "1.13.3") public class DiscoveryIssueException extends JUnitException { private static final long serialVersionUID = 1L; diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherDiscoveryRequestBuilder.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherDiscoveryRequestBuilder.java index d1fa66711079..d2596ede68df 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherDiscoveryRequestBuilder.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherDiscoveryRequestBuilder.java @@ -11,7 +11,7 @@ package org.junit.platform.launcher.core; import static org.apiguardian.api.API.Status.DEPRECATED; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import static org.junit.platform.launcher.LauncherConstants.OUTPUT_DIR_PROPERTY_NAME; @@ -302,7 +302,7 @@ public LauncherDiscoveryRequestBuilder listeners(LauncherDiscoveryListener... li * @see OutputDirectoryProvider * @see LauncherConstants#OUTPUT_DIR_PROPERTY_NAME */ - @API(status = EXPERIMENTAL, since = "1.12") + @API(status = MAINTAINED, since = "1.13.3") public LauncherDiscoveryRequestBuilder outputDirectoryProvider(OutputDirectoryProvider outputDirectoryProvider) { this.outputDirectoryProvider = Preconditions.notNull(outputDirectoryProvider, "outputDirectoryProvider must not be null"); diff --git a/junit-platform-reporting/src/main/java/org/junit/platform/reporting/open/xml/OpenTestReportGeneratingListener.java b/junit-platform-reporting/src/main/java/org/junit/platform/reporting/open/xml/OpenTestReportGeneratingListener.java index 822c6852959b..b724ee36fb2c 100644 --- a/junit-platform-reporting/src/main/java/org/junit/platform/reporting/open/xml/OpenTestReportGeneratingListener.java +++ b/junit-platform-reporting/src/main/java/org/junit/platform/reporting/open/xml/OpenTestReportGeneratingListener.java @@ -10,7 +10,7 @@ package org.junit.platform.reporting.open.xml; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.junit.platform.commons.util.StringUtils.isNotBlank; import static org.junit.platform.launcher.LauncherConstants.STDERR_REPORT_ENTRY_KEY; import static org.junit.platform.launcher.LauncherConstants.STDOUT_REPORT_ENTRY_KEY; @@ -96,7 +96,7 @@ * * @since 1.9 */ -@API(status = EXPERIMENTAL, since = "1.9") +@API(status = MAINTAINED, since = "1.13.3") public class OpenTestReportGeneratingListener implements TestExecutionListener { static final String ENABLED_PROPERTY_NAME = "junit.platform.reporting.open.xml.enabled"; diff --git a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/AfterSuite.java b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/AfterSuite.java index 77ff31333f1a..97a93f7f7758 100644 --- a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/AfterSuite.java +++ b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/AfterSuite.java @@ -10,7 +10,7 @@ package org.junit.platform.suite.api; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; @@ -70,6 +70,6 @@ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented -@API(status = EXPERIMENTAL, since = "1.11") +@API(status = MAINTAINED, since = "1.13.3") public @interface AfterSuite { } diff --git a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/BeforeSuite.java b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/BeforeSuite.java index c62d9ccdc040..1b0f89ac181a 100644 --- a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/BeforeSuite.java +++ b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/BeforeSuite.java @@ -10,7 +10,7 @@ package org.junit.platform.suite.api; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; @@ -70,6 +70,6 @@ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented -@API(status = EXPERIMENTAL, since = "1.11") +@API(status = MAINTAINED, since = "1.13.3") public @interface BeforeSuite { } diff --git a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/ConfigurationParametersResource.java b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/ConfigurationParametersResource.java index 6e370f69ff4c..2ce8e7f83287 100644 --- a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/ConfigurationParametersResource.java +++ b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/ConfigurationParametersResource.java @@ -10,7 +10,7 @@ package org.junit.platform.suite.api; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; @@ -39,7 +39,7 @@ @Target(ElementType.TYPE) @Inherited @Documented -@API(status = EXPERIMENTAL, since = "1.11") +@API(status = MAINTAINED, since = "1.13.3") @Repeatable(ConfigurationParametersResources.class) public @interface ConfigurationParametersResource { diff --git a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/ConfigurationParametersResources.java b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/ConfigurationParametersResources.java index 0897e77b4622..8726fd4f3f83 100644 --- a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/ConfigurationParametersResources.java +++ b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/ConfigurationParametersResources.java @@ -10,7 +10,7 @@ package org.junit.platform.suite.api; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; @@ -36,7 +36,7 @@ @Target(ElementType.TYPE) @Inherited @Documented -@API(status = EXPERIMENTAL, since = "1.11") +@API(status = MAINTAINED, since = "1.13.3") public @interface ConfigurationParametersResources { /** diff --git a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/Select.java b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/Select.java index f2fd4a47a370..e8de03805ddf 100644 --- a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/Select.java +++ b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/Select.java @@ -10,7 +10,7 @@ package org.junit.platform.suite.api; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; @@ -35,7 +35,7 @@ @Target(ElementType.TYPE) @Inherited @Documented -@API(status = EXPERIMENTAL, since = "1.11") +@API(status = MAINTAINED, since = "1.13.3") @Repeatable(Selects.class) public @interface Select { diff --git a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SelectClasses.java b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SelectClasses.java index 9964f7b68b68..064363d69198 100644 --- a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SelectClasses.java +++ b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SelectClasses.java @@ -10,7 +10,6 @@ package org.junit.platform.suite.api; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.annotation.Documented; @@ -57,7 +56,7 @@ * * @since 1.10 */ - @API(status = EXPERIMENTAL, since = "1.10") + @API(status = MAINTAINED, since = "1.13.3") String[] names() default {}; } diff --git a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SelectMethod.java b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SelectMethod.java index c1fa0f6dc40d..d86e273e3502 100644 --- a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SelectMethod.java +++ b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SelectMethod.java @@ -10,7 +10,7 @@ package org.junit.platform.suite.api; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; @@ -40,7 +40,7 @@ @Target(ElementType.TYPE) @Inherited @Documented -@API(status = EXPERIMENTAL, since = "1.10") +@API(status = MAINTAINED, since = "1.13.3") @Repeatable(SelectMethods.class) public @interface SelectMethod { diff --git a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SelectMethods.java b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SelectMethods.java index f3583156f325..6454363e95df 100644 --- a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SelectMethods.java +++ b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SelectMethods.java @@ -10,7 +10,7 @@ package org.junit.platform.suite.api; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; @@ -36,7 +36,7 @@ @Target(ElementType.TYPE) @Inherited @Documented -@API(status = EXPERIMENTAL, since = "1.10") +@API(status = MAINTAINED, since = "1.13.3") public @interface SelectMethods { /** diff --git a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/Selects.java b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/Selects.java index 63f52143916b..6215c409b7fc 100644 --- a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/Selects.java +++ b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/Selects.java @@ -10,7 +10,7 @@ package org.junit.platform.suite.api; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; @@ -36,7 +36,7 @@ @Target(ElementType.TYPE) @Inherited @Documented -@API(status = EXPERIMENTAL, since = "1.11") +@API(status = MAINTAINED, since = "1.13.3") public @interface Selects { /** diff --git a/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/EngineDiscoveryResults.java b/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/EngineDiscoveryResults.java index 901462794d31..376d29158b3e 100644 --- a/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/EngineDiscoveryResults.java +++ b/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/EngineDiscoveryResults.java @@ -11,7 +11,7 @@ package org.junit.platform.testkit.engine; import static java.util.Collections.unmodifiableList; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import java.util.List; @@ -28,7 +28,7 @@ * * @since 1.13 */ -@API(status = EXPERIMENTAL, since = "1.13") +@API(status = MAINTAINED, since = "1.13.3") public class EngineDiscoveryResults { private final TestDescriptor engineDescriptor; diff --git a/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/EngineTestKit.java b/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/EngineTestKit.java index 37398b4efd3e..d30d22f7ce57 100644 --- a/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/EngineTestKit.java +++ b/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/EngineTestKit.java @@ -13,7 +13,6 @@ import static java.util.Collections.emptySet; import static java.util.Collections.singleton; import static org.apiguardian.api.API.Status.DEPRECATED; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import static org.junit.platform.engine.support.store.NamespacedHierarchicalStore.CloseAction.closeAutoCloseables; @@ -159,7 +158,7 @@ public static Builder engine(TestEngine testEngine) { * @see #engine(String) * @see #engine(TestEngine) */ - @API(status = EXPERIMENTAL, since = "1.13") + @API(status = MAINTAINED, since = "1.13.3") public static EngineDiscoveryResults discover(String engineId, LauncherDiscoveryRequest discoveryRequest) { Preconditions.notBlank(engineId, "TestEngine ID must not be null or blank"); return discover(loadTestEngine(engineId.trim()), discoveryRequest); @@ -184,7 +183,7 @@ public static EngineDiscoveryResults discover(String engineId, LauncherDiscovery * @see #engine(String) * @see #engine(TestEngine) */ - @API(status = EXPERIMENTAL, since = "1.13") + @API(status = MAINTAINED, since = "1.13.3") public static EngineDiscoveryResults discover(TestEngine testEngine, LauncherDiscoveryRequest discoveryRequest) { Preconditions.notNull(testEngine, "TestEngine must not be null"); Preconditions.notNull(discoveryRequest, "EngineDiscoveryRequest must not be null"); @@ -531,7 +530,7 @@ public Builder enableImplicitConfigurationParameters(boolean enabled) { * @since 1.12 * @see OutputDirectoryProvider */ - @API(status = EXPERIMENTAL, since = "1.12") + @API(status = MAINTAINED, since = "1.13.3") public Builder outputDirectoryProvider(OutputDirectoryProvider outputDirectoryProvider) { this.requestBuilder.outputDirectoryProvider(outputDirectoryProvider); return this; @@ -550,7 +549,7 @@ public Builder outputDirectoryProvider(OutputDirectoryProvider outputDirectoryPr * @see #configurationParameter(String, String) * @see #configurationParameters(Map) */ - @API(status = EXPERIMENTAL, since = "1.13") + @API(status = MAINTAINED, since = "1.13.3") public EngineDiscoveryResults discover() { LauncherDiscoveryRequest request = this.requestBuilder.build(); return EngineTestKit.discover(this.testEngine, request); diff --git a/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/Event.java b/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/Event.java index 9d6187e5ccc1..7212c4dbdca2 100644 --- a/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/Event.java +++ b/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/Event.java @@ -10,7 +10,6 @@ package org.junit.platform.testkit.engine; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.MAINTAINED; import static org.junit.platform.commons.util.FunctionUtils.where; @@ -64,7 +63,7 @@ public static Event reportingEntryPublished(TestDescriptor testDescriptor, Repor * @since 1.12 * @see EventType#FILE_ENTRY_PUBLISHED */ - @API(status = EXPERIMENTAL, since = "1.12") + @API(status = MAINTAINED, since = "1.13.3") public static Event fileEntryPublished(TestDescriptor testDescriptor, FileEntry file) { Preconditions.notNull(file, "FileEntry must not be null"); return new Event(EventType.FILE_ENTRY_PUBLISHED, testDescriptor, file); diff --git a/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/EventConditions.java b/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/EventConditions.java index 4be237c109e0..9d661add752c 100644 --- a/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/EventConditions.java +++ b/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/EventConditions.java @@ -12,7 +12,6 @@ import static java.util.function.Predicate.isEqual; import static java.util.stream.Collectors.toList; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import static org.assertj.core.api.Assertions.allOf; @@ -257,7 +256,7 @@ public static Condition dynamicTestRegistered(Condition condition) * * @since 1.13 */ - @API(status = EXPERIMENTAL, since = "1.13") + @API(status = MAINTAINED, since = "1.13.3") public static Condition uniqueId(String uniqueId) { return uniqueId(UniqueId.parse(uniqueId)); } @@ -270,7 +269,7 @@ public static Condition uniqueId(String uniqueId) { * * @since 1.13 */ - @API(status = EXPERIMENTAL, since = "1.13") + @API(status = MAINTAINED, since = "1.13.3") public static Condition uniqueId(UniqueId uniqueId) { return uniqueId(new Condition<>(isEqual(uniqueId), "equal to '%s'", uniqueId)); } @@ -298,7 +297,7 @@ public static Condition uniqueIdSubstring(String uniqueIdSubstring) { * * @since 1.13 */ - @API(status = EXPERIMENTAL, since = "1.13") + @API(status = MAINTAINED, since = "1.13.3") public static Condition uniqueId(Condition condition) { return new Condition<>(byTestDescriptor(where(TestDescriptor::getUniqueId, condition::matches)), "descriptor with uniqueId %s", condition.description().value()); @@ -360,7 +359,7 @@ public static Condition displayName(String displayName) { * * @since 1.13 */ - @API(status = EXPERIMENTAL, since = "1.13") + @API(status = MAINTAINED, since = "1.13.3") public static Condition legacyReportingName(String legacyReportingName) { return new Condition<>( byTestDescriptor(where(TestDescriptor::getLegacyReportingName, isEqual(legacyReportingName))), @@ -532,7 +531,7 @@ public static Condition reportEntry(Map keyValuePairs) { * * @since 1.12 */ - @API(status = EXPERIMENTAL, since = "1.12") + @API(status = MAINTAINED, since = "1.13.3") public static Condition fileEntry(Predicate predicate) { return new Condition<>(byPayload(FileEntry.class, predicate), "event for file entry with custom predicate"); } diff --git a/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/EventStatistics.java b/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/EventStatistics.java index a0e38754ca61..19c34329a605 100644 --- a/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/EventStatistics.java +++ b/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/EventStatistics.java @@ -10,7 +10,6 @@ package org.junit.platform.testkit.engine; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.MAINTAINED; import static org.junit.platform.testkit.engine.Assertions.assertEquals; @@ -135,7 +134,7 @@ public EventStatistics reportingEntryPublished(long expected) { * @return this {@code EventStatistics} for method chaining * @since 1.12 */ - @API(status = EXPERIMENTAL, since = "1.12") + @API(status = MAINTAINED, since = "1.13.3") public EventStatistics fileEntryPublished(long expected) { this.executables.add( () -> assertEquals(expected, this.events.fileEntryPublished().count(), "file entry published")); diff --git a/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/EventType.java b/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/EventType.java index 9cef63ee24f9..25b23fef3f1b 100644 --- a/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/EventType.java +++ b/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/EventType.java @@ -10,7 +10,6 @@ package org.junit.platform.testkit.engine; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.MAINTAINED; import org.apiguardian.api.API; @@ -70,7 +69,7 @@ public enum EventType { * @since 1.12 * @see org.junit.platform.engine.EngineExecutionListener#fileEntryPublished(TestDescriptor, FileEntry) */ - @API(status = EXPERIMENTAL, since = "1.12") + @API(status = MAINTAINED, since = "1.13.3") FILE_ENTRY_PUBLISHED } diff --git a/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/Events.java b/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/Events.java index 6866116f3ff2..e656c1c82cfa 100644 --- a/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/Events.java +++ b/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/Events.java @@ -13,7 +13,6 @@ import static java.util.Collections.sort; import static java.util.function.Predicate.isEqual; import static java.util.stream.Collectors.toList; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.MAINTAINED; import static org.junit.platform.commons.util.FunctionUtils.where; import static org.junit.platform.testkit.engine.Event.byPayload; @@ -215,7 +214,7 @@ public Events reportingEntryPublished() { * @return the filtered {@code Events}; never {@code null} * @since 1.12 */ - @API(status = EXPERIMENTAL, since = "1.12") + @API(status = MAINTAINED, since = "1.13.3") public Events fileEntryPublished() { return new Events(eventsByType(EventType.FILE_ENTRY_PUBLISHED), this.category + " File Entry Published"); } diff --git a/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/ExecutionRecorder.java b/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/ExecutionRecorder.java index d27b058160da..fd904b7e2ca1 100644 --- a/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/ExecutionRecorder.java +++ b/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/ExecutionRecorder.java @@ -10,7 +10,6 @@ package org.junit.platform.testkit.engine; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.MAINTAINED; import java.util.List; @@ -89,7 +88,7 @@ public void reportingEntryPublished(TestDescriptor testDescriptor, ReportEntry e * * @since 1.12 */ - @API(status = EXPERIMENTAL, since = "1.12") + @API(status = MAINTAINED, since = "1.13.3") @Override public void fileEntryPublished(TestDescriptor testDescriptor, FileEntry file) { this.events.add(Event.fileEntryPublished(testDescriptor, file)); diff --git a/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/TestExecutionResultConditions.java b/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/TestExecutionResultConditions.java index f9b1b1f9c53c..53ce43099eab 100644 --- a/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/TestExecutionResultConditions.java +++ b/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/TestExecutionResultConditions.java @@ -12,7 +12,6 @@ import static java.util.function.Predicate.isEqual; import static java.util.stream.Collectors.toList; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.MAINTAINED; import static org.junit.platform.commons.util.FunctionUtils.where; @@ -95,7 +94,7 @@ public static Condition cause(Condition... conditions) { * @see #cause(Condition...) * @see #suppressed(int, Condition...) */ - @API(status = EXPERIMENTAL, since = "1.11") + @API(status = MAINTAINED, since = "1.13.3") @SafeVarargs @SuppressWarnings("varargs") public static Condition rootCause(Condition... conditions) { diff --git a/junit-vintage-engine/junit-vintage-engine.gradle.kts b/junit-vintage-engine/junit-vintage-engine.gradle.kts index 54d444b43c81..b3080a415bd5 100644 --- a/junit-vintage-engine/junit-vintage-engine.gradle.kts +++ b/junit-vintage-engine/junit-vintage-engine.gradle.kts @@ -22,6 +22,7 @@ dependencies { testImplementation(projects.junitPlatformLauncher) testImplementation(projects.junitPlatformSuiteEngine) testImplementation(projects.junitPlatformTestkit) + testImplementation(testFixtures(projects.junitPlatformCommons)) testImplementation(testFixtures(projects.junitJupiterApi)) testImplementation(testFixtures(projects.junitPlatformLauncher)) testImplementation(testFixtures(projects.junitPlatformReporting)) diff --git a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/Constants.java b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/Constants.java index 3d97979d2276..cdd0466a9cd9 100644 --- a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/Constants.java +++ b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/Constants.java @@ -10,7 +10,7 @@ package org.junit.vintage.engine; -import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; @@ -31,7 +31,7 @@ public final class Constants { * * @since 5.12 */ - @API(status = EXPERIMENTAL, since = "5.12") + @API(status = MAINTAINED, since = "5.13.3") public static final String PARALLEL_EXECUTION_ENABLED = "junit.vintage.execution.parallel.enabled"; /** @@ -43,7 +43,7 @@ public final class Constants { * * @since 5.12 */ - @API(status = EXPERIMENTAL, since = "5.12") + @API(status = MAINTAINED, since = "5.13.3") public static final String PARALLEL_POOL_SIZE = "junit.vintage.execution.parallel.pool-size"; /** @@ -55,7 +55,7 @@ public final class Constants { * * @since 5.12 */ - @API(status = EXPERIMENTAL, since = "5.12") + @API(status = MAINTAINED, since = "5.13.3") public static final String PARALLEL_CLASS_EXECUTION = "junit.vintage.execution.parallel.classes"; /** @@ -67,7 +67,7 @@ public final class Constants { * * @since 5.12 */ - @API(status = EXPERIMENTAL, since = "5.12") + @API(status = MAINTAINED, since = "5.13.3") public static final String PARALLEL_METHOD_EXECUTION = "junit.vintage.execution.parallel.methods"; private Constants() { diff --git a/junit-vintage-engine/src/test/java/org/junit/vintage/engine/VintageTestEngineExecutionTests.java b/junit-vintage-engine/src/test/java/org/junit/vintage/engine/VintageTestEngineExecutionTests.java index 8811f97d404d..415fbd235ba8 100644 --- a/junit-vintage-engine/src/test/java/org/junit/vintage/engine/VintageTestEngineExecutionTests.java +++ b/junit-vintage-engine/src/test/java/org/junit/vintage/engine/VintageTestEngineExecutionTests.java @@ -42,6 +42,7 @@ import org.assertj.core.api.Condition; import org.junit.AssumptionViolatedException; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.DisabledInEclipse; import org.junit.platform.engine.EngineExecutionListener; import org.junit.platform.engine.ExecutionRequest; import org.junit.platform.engine.TestDescriptor; @@ -862,6 +863,7 @@ void executesJUnit4TestCaseWithRunnerWithDuplicateChangingChildDescriptions() { } @Test + @DisabledInEclipse void executesUnrolledSpockFeatureMethod() { Class testClass = SpockTestCaseWithUnrolledAndRegularFeatureMethods.class; var request = LauncherDiscoveryRequestBuilder.request().selectors( @@ -880,6 +882,7 @@ void executesUnrolledSpockFeatureMethod() { } @Test + @DisabledInEclipse void executesRegularSpockFeatureMethod() { Class testClass = SpockTestCaseWithUnrolledAndRegularFeatureMethods.class; var request = LauncherDiscoveryRequestBuilder.request().selectors(selectMethod(testClass, "regular")).build(); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/ConditionEvaluationResultTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/ConditionEvaluationResultTests.java new file mode 100644 index 000000000000..4407ac792e46 --- /dev/null +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/ConditionEvaluationResultTests.java @@ -0,0 +1,127 @@ +/* + * Copyright 2015-2025 the original author or authors. + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v2.0 which + * accompanies this distribution and is available at + * + * https://www.eclipse.org/legal/epl-v20.html + */ + +package org.junit.jupiter.api.condition; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ConditionEvaluationResult; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.NullSource; +import org.junit.jupiter.params.provider.ValueSource; + +/** + * Unit tests for {@link ConditionEvaluationResult}. + * + * @since 5.13.3 + */ +class ConditionEvaluationResultTests { + + @Test + void enabledWithReason() { + var result = ConditionEvaluationResult.enabled("reason"); + + assertThat(result.isDisabled()).isFalse(); + assertThat(result.getReason()).contains("reason"); + assertThat(result).asString()// + .isEqualTo("ConditionEvaluationResult [enabled = true, reason = 'reason']"); + } + + @BlankReasonsTest + void enabledWithBlankReason(String reason) { + var result = ConditionEvaluationResult.enabled(reason); + + assertThat(result.isDisabled()).isFalse(); + assertThat(result.getReason()).isEmpty(); + assertThat(result).asString()// + .isEqualTo("ConditionEvaluationResult [enabled = true, reason = '']"); + } + + @Test + void disabledWithDefaultReason() { + var result = ConditionEvaluationResult.disabled("default"); + + assertThat(result.isDisabled()).isTrue(); + assertThat(result.getReason()).contains("default"); + assertThat(result).asString()// + .isEqualTo("ConditionEvaluationResult [enabled = false, reason = 'default']"); + } + + @BlankReasonsTest + void disabledWithBlankDefaultReason(String reason) { + var result = ConditionEvaluationResult.disabled(reason); + + assertThat(result.isDisabled()).isTrue(); + assertThat(result.getReason()).isEmpty(); + assertThat(result).asString()// + .isEqualTo("ConditionEvaluationResult [enabled = false, reason = '']"); + } + + @BlankReasonsTest + void disabledWithDefaultReasonAndBlankCustomReason(String customReason) { + var result = ConditionEvaluationResult.disabled("default", customReason); + + assertThat(result.isDisabled()).isTrue(); + assertThat(result.getReason()).contains("default"); + assertThat(result).asString()// + .isEqualTo("ConditionEvaluationResult [enabled = false, reason = 'default']"); + } + + @BlankReasonsTest + void disabledWithBlankDefaultReasonAndCustomReason(String reason) { + var result = ConditionEvaluationResult.disabled(reason, "custom"); + + assertThat(result.isDisabled()).isTrue(); + assertThat(result.getReason()).contains("custom"); + assertThat(result).asString().isEqualTo("ConditionEvaluationResult [enabled = false, reason = 'custom']"); + } + + @BlankReasonsTest + void disabledWithBlankDefaultReasonAndBlankCustomReason(String reason) { + // We intentionally use the reason as both the default and custom reason. + var result = ConditionEvaluationResult.disabled(reason, reason); + + assertThat(result.isDisabled()).isTrue(); + assertThat(result.getReason()).isEmpty(); + assertThat(result).asString()// + .isEqualTo("ConditionEvaluationResult [enabled = false, reason = '']"); + } + + @Test + void disabledWithDefaultReasonAndCustomReason() { + disabledWithDefaultReasonAndCustomReason("default", "custom"); + } + + @Test + void disabledWithDefaultReasonAndCustomReasonWithLeadingAndTrailingWhitespace() { + disabledWithDefaultReasonAndCustomReason(" default ", " custom "); + } + + private static void disabledWithDefaultReasonAndCustomReason(String defaultReason, String customReason) { + var result = ConditionEvaluationResult.disabled(defaultReason, customReason); + + assertThat(result.isDisabled()).isTrue(); + assertThat(result.getReason()).contains("default ==> custom"); + assertThat(result).asString()// + .isEqualTo("ConditionEvaluationResult [enabled = false, reason = 'default ==> custom']"); + } + + @Retention(RetentionPolicy.RUNTIME) + @ParameterizedTest(name = "[{index}] reason=\"{0}\"") + @NullSource + @ValueSource(strings = { "", " ", " ", "\t", "\n" }) + @interface BlankReasonsTest { + } + +} diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/AbstractJupiterTestEngineTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/AbstractJupiterTestEngineTests.java index 0dcd074d74f8..890cf8eab241 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/AbstractJupiterTestEngineTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/AbstractJupiterTestEngineTests.java @@ -10,6 +10,7 @@ package org.junit.jupiter.engine; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectMethod; @@ -22,6 +23,7 @@ import org.junit.platform.engine.DiscoveryIssue.Severity; import org.junit.platform.engine.DiscoverySelector; +import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.UniqueId; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder; @@ -60,6 +62,12 @@ protected EngineExecutionResults executeTests(LauncherDiscoveryRequest request) return EngineTestKit.execute(this.engine, request); } + protected TestDescriptor discoverTestsWithoutIssues(LauncherDiscoveryRequest request) { + var results = discoverTests(request); + assertThat(results.getDiscoveryIssues()).isEmpty(); + return results.getEngineDescriptor(); + } + protected EngineDiscoveryResults discoverTestsForClass(Class testClass) { return discoverTests(selectClass(testClass)); } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/ClassTemplateInvocationTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/ClassTemplateInvocationTests.java index cd15da225011..8d51a155ff35 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/ClassTemplateInvocationTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/ClassTemplateInvocationTests.java @@ -87,6 +87,7 @@ import org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor; import org.junit.jupiter.engine.descriptor.TestTemplateInvocationTestDescriptor; import org.junit.jupiter.engine.descriptor.TestTemplateTestDescriptor; +import org.junit.jupiter.params.ParameterizedClass; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.junit.platform.engine.TestTag; @@ -978,8 +979,10 @@ void templateWithPreparations() { @Test void propagatesTagsFromEnclosingClassesToNestedClassTemplates() { - var engineDescriptor = discoverTestsForClass( - NestedClassTemplateWithTagOnEnclosingClassTestCase.class).getEngineDescriptor(); + var request = defaultRequest() // + .selectors(selectClass(NestedClassTemplateWithTagOnEnclosingClassTestCase.class)) // + .build(); + var engineDescriptor = discoverTestsWithoutIssues(request); var classDescriptor = getOnlyElement(engineDescriptor.getChildren()); var nestedClassTemplateDescriptor = getOnlyElement(classDescriptor.getChildren()); @@ -989,6 +992,17 @@ void propagatesTagsFromEnclosingClassesToNestedClassTemplates() { .containsExactlyInAnyOrder("top-level", "nested"); } + @Test + void ignoresComposedAnnotations() { + var request = defaultRequest() // + .selectors(selectClass(ParameterizedClass.class)) // + .build(); + + var engineDescriptor = discoverTestsWithoutIssues(request); + + assertThat(engineDescriptor.getDescendants()).isEmpty(); + } + // ------------------------------------------------------------------- private static Stream allReportEntryValues(EngineExecutionResults results) { diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/NestedTestClassesTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/NestedTestClassesTests.java index bfb3a8a80fd9..677be2e5cde3 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/NestedTestClassesTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/NestedTestClassesTests.java @@ -19,10 +19,13 @@ import static org.junit.platform.engine.discovery.DiscoverySelectors.selectPackage; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectUniqueId; import static org.junit.platform.launcher.LauncherConstants.CRITICAL_DISCOVERY_ISSUE_SEVERITY_PROPERTY_NAME; -import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import static org.junit.platform.testkit.engine.EventConditions.finishedWithFailure; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.message; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; import java.util.List; import java.util.function.Consumer; import java.util.regex.Pattern; @@ -38,6 +41,7 @@ import org.junit.jupiter.engine.NestedTestClassesTests.OuterClass.NestedClass.RecursiveNestedSiblingClass; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.ValueSource; import org.junit.platform.engine.DiscoveryIssue.Severity; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.support.descriptor.ClassSource; @@ -56,8 +60,8 @@ class NestedTestClassesTests extends AbstractJupiterTestEngineTests { @Test void nestedTestsAreCorrectlyDiscovered() { - LauncherDiscoveryRequest request = request().selectors(selectClass(TestCaseWithNesting.class)).build(); - TestDescriptor engineDescriptor = discoverTests(request).getEngineDescriptor(); + LauncherDiscoveryRequest request = defaultRequest().selectors(selectClass(TestCaseWithNesting.class)).build(); + TestDescriptor engineDescriptor = discoverTestsWithoutIssues(request); assertEquals(5, engineDescriptor.getDescendants().size(), "# resolved test descriptors"); } @@ -93,8 +97,9 @@ static List>> nestedTestsAreExec @Test void doublyNestedTestsAreCorrectlyDiscovered() { - LauncherDiscoveryRequest request = request().selectors(selectClass(TestCaseWithDoubleNesting.class)).build(); - TestDescriptor engineDescriptor = discoverTests(request).getEngineDescriptor(); + LauncherDiscoveryRequest request = defaultRequest().selectors( + selectClass(TestCaseWithDoubleNesting.class)).build(); + TestDescriptor engineDescriptor = discoverTestsWithoutIssues(request); assertEquals(8, engineDescriptor.getDescendants().size(), "# resolved test descriptors"); } @@ -245,6 +250,22 @@ void doesNotReportDiscoveryIssueForAbstractInnerClass() { assertThat(discoveryIssues).isEmpty(); } + @Test + void nestedTestsWithCustomAnnotationAreCorrectlyDiscovered() { + LauncherDiscoveryRequest request = defaultRequest().selectors( + selectClass(CustomAnnotationTestCase.class)).build(); + TestDescriptor engineDescriptor = discoverTestsWithoutIssues(request); + assertEquals(3, engineDescriptor.getDescendants().size(), "# resolved test descriptors"); + } + + @ParameterizedTest + @ValueSource(classes = { TopLevelComposedNested.class, CustomAnnotationTestCase.MyNested.class }) + void ignoresComposedAnnotations(Class annotationType) { + LauncherDiscoveryRequest request = defaultRequest().selectors(selectClass(annotationType)).build(); + TestDescriptor engineDescriptor = discoverTestsWithoutIssues(request); + assertEquals(0, engineDescriptor.getDescendants().size(), "# resolved test descriptors"); + } + private void assertNestedCycle(Class start, Class from, Class to) { var results = executeTestsForClass(start); var expectedMessage = String.format( @@ -254,6 +275,40 @@ private void assertNestedCycle(Class start, Class from, Class to) { .haveExactly(1, finishedWithFailure(message(it -> it.contains(expectedMessage)))); } + @Test + void discoversButWarnsAboutTopLevelNestedTestClasses() { + var results = discoverTestsForClass(TopLevelNestedTestCase.class); + + var engineDescriptor = results.getEngineDescriptor(); + assertEquals(2, engineDescriptor.getDescendants().size(), "# resolved test descriptors"); + + var discoveryIssues = results.getDiscoveryIssues(); + assertThat(discoveryIssues).hasSize(1); + assertThat(discoveryIssues.getFirst().message()) // + .isEqualTo( + "Top-level class '%s' must not be annotated with @Nested. " + + "It will be executed anyway for backward compatibility. " + + "You should remove the @Nested annotation to resolve this warning.", + TopLevelNestedTestCase.class.getName()); + } + + @Test + void discoversButWarnsAboutStaticNestedTestClasses() { + var results = discoverTestsForClass(StaticNestedTestCase.TestCase.class); + + var engineDescriptor = results.getEngineDescriptor(); + assertEquals(2, engineDescriptor.getDescendants().size(), "# resolved test descriptors"); + + var discoveryIssues = results.getDiscoveryIssues(); + assertThat(discoveryIssues).hasSize(1); + assertThat(discoveryIssues.getFirst().message()) // + .isEqualTo( + "@Nested class '%s' must not be static. " + + "It will only be executed if discovered as a standalone test class. " + + "You should remove the annotation or make it non-static to resolve this warning.", + StaticNestedTestCase.TestCase.class.getName()); + } + // ------------------------------------------------------------------- @SuppressWarnings("JUnitMalformedDeclaration") @@ -451,4 +506,23 @@ class NestedTests extends AbstractInnerClass { } } + static class CustomAnnotationTestCase { + + @Nested + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE) + @interface MyNested { + } + + @SuppressWarnings({ "JUnitMalformedDeclaration", "InnerClassMayBeStatic" }) + @MyNested + class Inner { + + @Test + void test() { + + } + } + } + } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/StaticNestedTestCase.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/StaticNestedTestCase.java new file mode 100644 index 000000000000..a68851a90ada --- /dev/null +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/StaticNestedTestCase.java @@ -0,0 +1,26 @@ +/* + * Copyright 2015-2025 the original author or authors. + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v2.0 which + * accompanies this distribution and is available at + * + * https://www.eclipse.org/legal/epl-v20.html + */ + +package org.junit.jupiter.engine; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +class StaticNestedTestCase { + + @SuppressWarnings("JUnitMalformedDeclaration") + @Nested + static class TestCase { + @Test + void test() { + } + } + +} diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/TopLevelComposedNested.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/TopLevelComposedNested.java new file mode 100644 index 000000000000..7f711f8cb4dc --- /dev/null +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/TopLevelComposedNested.java @@ -0,0 +1,24 @@ +/* + * Copyright 2015-2025 the original author or authors. + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v2.0 which + * accompanies this distribution and is available at + * + * https://www.eclipse.org/legal/epl-v20.html + */ + +package org.junit.jupiter.engine; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.junit.jupiter.api.Nested; + +@Nested +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface TopLevelComposedNested { +} diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/TopLevelNestedTestCase.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/TopLevelNestedTestCase.java new file mode 100644 index 000000000000..da2b30026e9e --- /dev/null +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/TopLevelNestedTestCase.java @@ -0,0 +1,22 @@ +/* + * Copyright 2015-2025 the original author or authors. + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v2.0 which + * accompanies this distribution and is available at + * + * https://www.eclipse.org/legal/epl-v20.html + */ + +package org.junit.jupiter.engine; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +@Nested +public class TopLevelNestedTestCase { + + @Test + void test() { + } +} diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/discovery/DiscoveryTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/discovery/DiscoveryTests.java index 4a7db2ad7f42..02fa1eb5b01d 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/discovery/DiscoveryTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/discovery/DiscoveryTests.java @@ -14,9 +14,11 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; +import static org.junit.jupiter.api.Assumptions.assumeFalse; import static org.junit.jupiter.api.Named.named; import static org.junit.jupiter.engine.discovery.JupiterUniqueIdBuilder.uniqueIdForTestTemplateMethod; import static org.junit.jupiter.params.provider.Arguments.argumentSet; +import static org.junit.platform.commons.test.IdeUtils.runningInEclipse; import static org.junit.platform.commons.util.CollectionUtils.getOnlyElement; import static org.junit.platform.engine.discovery.ClassNameFilter.includeClassNamePatterns; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; @@ -39,6 +41,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInfo; import org.junit.jupiter.api.TestTemplate; +import org.junit.jupiter.api.extension.DisabledInEclipse; import org.junit.jupiter.engine.AbstractJupiterTestEngineTests; import org.junit.jupiter.engine.JupiterTestEngine; import org.junit.jupiter.engine.descriptor.ClassTestDescriptor; @@ -47,6 +50,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.ValueSource; import org.junit.platform.engine.DiscoveryIssue; import org.junit.platform.engine.DiscoveryIssue.Severity; import org.junit.platform.engine.TestDescriptor; @@ -74,6 +78,50 @@ void doNotDiscoverAbstractTestClass() { assertEquals(0, engineDescriptor.getDescendants().size(), "# resolved test descriptors"); } + @ParameterizedTest + @ValueSource(strings = { "org.junit.jupiter.engine.discovery.DiscoveryTests$InterfaceTestCase", + "org.junit.jupiter.engine.kotlin.KotlinInterfaceTestCase" }) + void doNotDiscoverTestInterface(String className) { + + assumeFalse(runningInEclipse() && className.contains(".kotlin.")); + + LauncherDiscoveryRequest request = defaultRequest().selectors(selectClass(className)).build(); + TestDescriptor engineDescriptor = discoverTestsWithoutIssues(request); + assertEquals(0, engineDescriptor.getDescendants().size(), "# resolved test descriptors"); + } + + @Test + @DisabledInEclipse + void doNotDiscoverGeneratedKotlinDefaultImplsClass() { + LauncherDiscoveryRequest request = defaultRequest() // + .selectors(selectClass("org.junit.jupiter.engine.kotlin.KotlinInterfaceTestCase$DefaultImpls")) // + .build(); + TestDescriptor engineDescriptor = discoverTestsWithoutIssues(request); + assertEquals(0, engineDescriptor.getDescendants().size(), "# resolved test descriptors"); + } + + @Test + @DisabledInEclipse + void discoverDeclaredKotlinDefaultImplsClass() { + LauncherDiscoveryRequest request = defaultRequest().selectors( + selectClass("org.junit.jupiter.engine.kotlin.KotlinDefaultImplsTestCase$DefaultImpls")).build(); + TestDescriptor engineDescriptor = discoverTestsWithoutIssues(request); + assertEquals(2, engineDescriptor.getDescendants().size(), "# resolved test descriptors"); + } + + @ParameterizedTest + @ValueSource(strings = { + "org.junit.jupiter.engine.discovery.DiscoveryTests$ConcreteImplementationOfInterfaceTestCase", + "org.junit.jupiter.engine.kotlin.KotlinInterfaceImplementationTestCase" }) + void discoverTestClassInheritingTestsFromInterface(String className) { + + assumeFalse(runningInEclipse() && className.contains(".kotlin.")); + + LauncherDiscoveryRequest request = defaultRequest().selectors(selectClass(className)).build(); + TestDescriptor engineDescriptor = discoverTestsWithoutIssues(request); + assertEquals(2, engineDescriptor.getDescendants().size(), "# resolved test descriptors"); + } + @Test void discoverMethodByUniqueId() { LauncherDiscoveryRequest request = defaultRequest().selectors( @@ -257,8 +305,8 @@ void reportsWarningForInvalidNestedTestClass(LauncherDiscoveryRequest request) { .isEqualTo("@Nested class '%s' must not be private. It will not be executed.", InvalidTestCases.InvalidTestClassTestCase.Inner.class.getName()); assertThat(discoveryIssues.getLast().message()) // - .isEqualTo("@Nested class '%s' must not be static. It will not be executed.", - InvalidTestCases.InvalidTestClassTestCase.Inner.class.getName()); + .startsWith("@Nested class '%s' must not be static.".formatted( + InvalidTestCases.InvalidTestClassTestCase.Inner.class.getName())); } static List> requestsForTestClassWithInvalidNestedTestClass() { @@ -361,12 +409,6 @@ void reportsWarningsForBlankDisplayNames() throws Exception { .contains(org.junit.platform.engine.support.descriptor.MethodSource.from(method)); } - private TestDescriptor discoverTestsWithoutIssues(LauncherDiscoveryRequest request) { - var results = super.discoverTests(request); - assertThat(results.getDiscoveryIssues()).isEmpty(); - return results.getEngineDescriptor(); - } - // ------------------------------------------------------------------- @SuppressWarnings("unused") @@ -530,4 +572,13 @@ void test() { } } + interface InterfaceTestCase { + @Test + default void test() { + } + } + + static class ConcreteImplementationOfInterfaceTestCase implements InterfaceTestCase { + } + } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/discovery/predicates/TestClassPredicatesTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/discovery/predicates/TestClassPredicatesTests.java index bacd663d33df..34d5f9ae541a 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/discovery/predicates/TestClassPredicatesTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/discovery/predicates/TestClassPredicatesTests.java @@ -254,7 +254,9 @@ void staticNestedClassEvaluatesToFalse() { assertThat(predicates.isAnnotatedWithNestedAndValid).rejects(candidate); var issue = DiscoveryIssue.builder(Severity.WARNING, - "@Nested class '%s' must not be static. It will not be executed.".formatted(candidate.getName())) // + "@Nested class '%s' must not be static. ".formatted(candidate.getName()) + + "It will only be executed if discovered as a standalone test class. " + + "You should remove the annotation or make it non-static to resolve this warning.") // .source(ClassSource.from(candidate)) // .build(); assertThat(discoveryIssues.stream().distinct()).containsExactly(issue); @@ -268,8 +270,9 @@ void topLevelClassEvaluatesToFalse() { assertThat(predicates.isAnnotatedWithNestedAndValid).rejects(candidate); var issue = DiscoveryIssue.builder(Severity.WARNING, - "@Nested class '%s' must not be a top-level class. It will not be executed.".formatted( - candidate.getName())) // + ("Top-level class '%s' must not be annotated with @Nested. ".formatted(candidate.getName()) + + "It will be executed anyway for backward compatibility. " + + "You should remove the @Nested annotation to resolve this warning.")) // .source(ClassSource.from(candidate)) // .build(); assertThat(discoveryIssues.stream().distinct()).containsExactly(issue); @@ -312,7 +315,9 @@ class LocalClass { assertThat(predicates.isAnnotatedWithNestedAndValid).rejects(candidate); var issue = DiscoveryIssue.builder(Severity.WARNING, - "@Nested class '%s' must not be static. It will not be executed.".formatted(candidate.getName())) // + "@Nested class '%s' must not be static. ".formatted(candidate.getName()) + + "It will only be executed if discovered as a standalone test class. " + + "You should remove the annotation or make it non-static to resolve this warning.") // .source(ClassSource.from(candidate)) // .build(); assertThat(discoveryIssues.stream().distinct()).containsExactly(issue); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/OrderedClassTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/OrderedClassTests.java index b1e163d7cfa9..bd5b4e59465b 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/OrderedClassTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/OrderedClassTests.java @@ -204,7 +204,9 @@ private static void assertIneffectiveOrderAnnotationIssues(List assertThat(discoveryIssues).extracting(DiscoveryIssue::severity).containsOnly(Severity.INFO); assertThat(discoveryIssues).extracting(DiscoveryIssue::message) // .allMatch(it -> it.startsWith("Ineffective @Order annotation on class") - && it.endsWith("It will not be applied because ClassOrderer.OrderAnnotation is not in use.")); + && it.contains("It will not be applied because ClassOrderer.OrderAnnotation is not in use.") + && it.endsWith( + "Note that the annotation may be either directly present or meta-present on the class.")); assertThat(discoveryIssues).extracting(DiscoveryIssue::source).extracting(Optional::orElseThrow) // .containsExactlyInAnyOrder(ClassSource.from(A_TestCase.class), ClassSource.from(C_TestCase.class)); } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/OrderedMethodTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/OrderedMethodTests.java index 0517a6dd026a..0fe769ae6b2f 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/OrderedMethodTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/OrderedMethodTests.java @@ -394,7 +394,9 @@ private static void assertIneffectiveOrderAnnotationIssues(List assertThat(discoveryIssues).extracting(DiscoveryIssue::severity).containsOnly(Severity.INFO); assertThat(discoveryIssues).extracting(DiscoveryIssue::message) // .allMatch(it -> it.startsWith("Ineffective @Order annotation on method") - && it.endsWith("It will not be applied because MethodOrderer.OrderAnnotation is not in use.")); + && it.contains("It will not be applied because MethodOrderer.OrderAnnotation is not in use.") + && it.endsWith( + "Note that the annotation may be either directly present or meta-present on the method.")); var testClass = WithoutTestMethodOrderTestCase.class; assertThat(discoveryIssues).extracting(DiscoveryIssue::source).extracting(Optional::orElseThrow) // .containsExactlyInAnyOrder(MethodSource.from(testClass.getDeclaredMethod("test1")), diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TimeoutInvocationFactoryTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TimeoutInvocationFactoryTests.java index b630fd112054..b67d0bcf2a00 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TimeoutInvocationFactoryTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TimeoutInvocationFactoryTests.java @@ -18,7 +18,7 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout.ThreadMode; -import org.junit.jupiter.api.condition.DisabledIf; +import org.junit.jupiter.api.extension.DisabledInEclipse; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtensionContext.Store; import org.junit.jupiter.api.extension.InvocationInterceptor.Invocation; @@ -35,7 +35,7 @@ // Mockito cannot mock this class: class org.junit.jupiter.engine.execution.NamespaceAwareStore. // You are seeing this disclaimer because Mockito is configured to create inlined mocks. // Byte Buddy could not instrument all classes within the mock's type hierarchy. -@DisabledIf(value = "runningInEclipse", disabledReason = "Mockito cannot create a spy for NamespaceAwareStore using the inline MockMaker in Eclipse IDE") +@DisabledInEclipse("Mockito cannot create a spy for NamespaceAwareStore using the inline MockMaker in Eclipse IDE") @DisplayName("TimeoutInvocationFactory") @ExtendWith(MockitoExtension.class) class TimeoutInvocationFactoryTests { @@ -97,13 +97,4 @@ void shouldCreateTimeoutInvocationForSeparateThreadTimeoutThreadMode() { assertThat(invocation).isInstanceOf(SeparateThreadTimeoutInvocation.class); } - /** - * Determine if the current code is running in the Eclipse IDE. - *

Copied from {@code org.springframework.core.testfixture.ide.IdeUtils}. - */ - static boolean runningInEclipse() { - return StackWalker.getInstance().walk( - stream -> stream.anyMatch(stackFrame -> stackFrame.getClassName().startsWith("org.eclipse.jdt"))); - } - } diff --git a/jupiter-tests/src/test/kotlin/org/junit/jupiter/engine/kotlin/KotlinDefaultImplsTestCase.kt b/jupiter-tests/src/test/kotlin/org/junit/jupiter/engine/kotlin/KotlinDefaultImplsTestCase.kt new file mode 100644 index 000000000000..90b97bd67e07 --- /dev/null +++ b/jupiter-tests/src/test/kotlin/org/junit/jupiter/engine/kotlin/KotlinDefaultImplsTestCase.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2015-2025 the original author or authors. + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v2.0 which + * accompanies this distribution and is available at + * + * https://www.eclipse.org/legal/epl-v20.html + */ +package org.junit.jupiter.engine.kotlin + +import org.junit.jupiter.api.Test + +class KotlinDefaultImplsTestCase { + @Suppress("JUnitMalformedDeclaration") + class DefaultImpls { + @Test + fun test() { + } + } +} diff --git a/jupiter-tests/src/test/kotlin/org/junit/jupiter/engine/kotlin/KotlinInterfaceImplementationTestCase.kt b/jupiter-tests/src/test/kotlin/org/junit/jupiter/engine/kotlin/KotlinInterfaceImplementationTestCase.kt new file mode 100644 index 000000000000..82be8a13cae1 --- /dev/null +++ b/jupiter-tests/src/test/kotlin/org/junit/jupiter/engine/kotlin/KotlinInterfaceImplementationTestCase.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2015-2025 the original author or authors. + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v2.0 which + * accompanies this distribution and is available at + * + * https://www.eclipse.org/legal/epl-v20.html + */ +package org.junit.jupiter.engine.kotlin + +class KotlinInterfaceImplementationTestCase : KotlinInterfaceTestCase diff --git a/jupiter-tests/src/test/kotlin/org/junit/jupiter/engine/kotlin/KotlinInterfaceTestCase.kt b/jupiter-tests/src/test/kotlin/org/junit/jupiter/engine/kotlin/KotlinInterfaceTestCase.kt new file mode 100644 index 000000000000..1df74af930ca --- /dev/null +++ b/jupiter-tests/src/test/kotlin/org/junit/jupiter/engine/kotlin/KotlinInterfaceTestCase.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2015-2025 the original author or authors. + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v2.0 which + * accompanies this distribution and is available at + * + * https://www.eclipse.org/legal/epl-v20.html + */ +package org.junit.jupiter.engine.kotlin + +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInfo + +interface KotlinInterfaceTestCase { + @Test + fun test(testInfo: TestInfo) { + } +} diff --git a/platform-tests/src/test/java/org/junit/platform/commons/support/scanning/DefaultClasspathScannerTests.java b/platform-tests/src/test/java/org/junit/platform/commons/support/scanning/DefaultClasspathScannerTests.java index 26349cb7ce6f..4ca7f01c4f6f 100644 --- a/platform-tests/src/test/java/org/junit/platform/commons/support/scanning/DefaultClasspathScannerTests.java +++ b/platform-tests/src/test/java/org/junit/platform/commons/support/scanning/DefaultClasspathScannerTests.java @@ -44,6 +44,7 @@ import java.util.stream.Collectors; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.DisabledInEclipse; import org.junit.jupiter.api.fixtures.TrackLogRecords; import org.junit.jupiter.api.io.TempDir; import org.junit.platform.commons.PreconditionViolationException; @@ -301,8 +302,8 @@ void scanForResourcesInPackage() { uriOf("/org/junit/platform/commons/other-example.resource")); } - @Test - // #2500 + @Test // #2500 + @DisabledInEclipse void scanForClassesInPackageWithinModulesSharingNamePrefix(@TempDir Path temp) throws Exception { var moduleSourcePath = Path.of(getClass().getResource("/modules-2500/").toURI()).toString(); run("javac", "--module", "foo,foo.bar", "--module-source-path", moduleSourcePath, "-d", temp.toString()); diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/core/ClasspathAlignmentCheckerTests.java b/platform-tests/src/test/java/org/junit/platform/launcher/core/ClasspathAlignmentCheckerTests.java index e9b75c3bbd51..f53229d9f0af 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/core/ClasspathAlignmentCheckerTests.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/core/ClasspathAlignmentCheckerTests.java @@ -24,6 +24,7 @@ import io.github.classgraph.PackageInfo; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.DisabledInEclipse; class ClasspathAlignmentCheckerTests { @@ -58,6 +59,7 @@ void wrapsLinkageErrorForUnalignedClasspath() { } @Test + @DisabledInEclipse void allRootPackagesAreChecked() { var allowedFileNames = Pattern.compile("junit-(?:platform|jupiter|vintage)-.+[\\d.]+(?:-SNAPSHOT)?\\.jar"); var classGraph = new ClassGraph() //