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() // pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy