diff --git a/.github/actions/run-gradle/action.yml b/.github/actions/run-gradle/action.yml index a4b1bc129f6c..6b0b94bc64e6 100644 --- a/.github/actions/run-gradle/action.yml +++ b/.github/actions/run-gradle/action.yml @@ -19,7 +19,7 @@ runs: with: arguments: | -Porg.gradle.java.installations.auto-download=false - -Penterprise.predictiveTestSelection.enabled=${{ github.event_name == 'pull_request' }} + -Pjunit.develocity.predictiveTestSelection.enabled=${{ github.event_name == 'pull_request' }} "-Dscan.value.GitHub job=${{ github.job }}" javaToolchains ${{ inputs.arguments }} diff --git a/.github/workflows/cross-version.yml b/.github/workflows/cross-version.yml index 03db008121f5..125b051d0088 100644 --- a/.github/workflows/cross-version.yml +++ b/.github/workflows/cross-version.yml @@ -10,9 +10,7 @@ on: - '*' env: - ENTERPRISE_TESTDISTRIBUTION_ENABLED: true - BUILDCACHE_USERNAME: ${{ secrets.BUILD_CACHE_USERNAME }} - BUILDCACHE_PASSWORD: ${{ secrets.BUILD_CACHE_PASSWORD }} + JUNIT_DEVELOCITY_TESTDISTRIBUTION_ENABLED: true GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }} jobs: diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b8c1d24b0e54..7a449b0c697c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -10,9 +10,7 @@ on: - '*' env: - ENTERPRISE_TESTDISTRIBUTION_ENABLED: true - BUILDCACHE_USERNAME: ${{ secrets.BUILD_CACHE_USERNAME }} - BUILDCACHE_PASSWORD: ${{ secrets.BUILD_CACHE_PASSWORD }} + JUNIT_DEVELOCITY_TESTDISTRIBUTION_ENABLED: true GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }} jobs: diff --git a/README.md b/README.md index 2f3c0be2b3ad..6308dd68cb7d 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ This repository is the home of _JUnit 5_. ## Latest Releases -- General Availability (GA): [JUnit 5.10.1](https://github.com/junit-team/junit5/releases/tag/r5.10.1) (November 5, 2023) +- General Availability (GA): [JUnit 5.10.2](https://github.com/junit-team/junit5/releases/tag/r5.10.2) (February 4, 2024) - Preview (Milestone/Release Candidate): N/A ## Documentation diff --git a/documentation/src/docs/asciidoc/release-notes/index.adoc b/documentation/src/docs/asciidoc/release-notes/index.adoc index bec921094623..802d49ab4a01 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.10.2.adoc[] + include::{basedir}/release-notes-5.10.1.adoc[] include::{basedir}/release-notes-5.10.0.adoc[] diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-5.10.2.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-5.10.2.adoc new file mode 100644 index 000000000000..1558506cb03c --- /dev/null +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-5.10.2.adoc @@ -0,0 +1,63 @@ +[[release-notes-5.10.2]] +== 5.10.2 + +*Date of Release:* February 4, 2024 + +*Scope:* minor bug fixes and changes since 5.10.1. + +For a complete list of all _closed_ issues and pull requests for this release, consult the +link:{junit5-repo}+/milestone/73?closed=1+[5.10.2] milestone page in the JUnit repository +on GitHub. + + +[[release-notes-5.10.2-junit-platform]] +=== JUnit Platform + +==== Bug Fixes + +* The `junit-platform-launcher` may now be used as a Java module when + `junit.platform.launcher.interceptors.enabled` is set to `true`. + - See issue link:https://github.com/junit-team/junit5/issues/3561[#3561] for details. + +==== Deprecations and Breaking Changes + +* Field predicates are no longer applied eagerly while searching the type hierarchy. + - This reverts changes made in 5.10.1 that affected `findFields(...)` and + `streamFields(...)` in `ReflectionSupport` as well as `findAnnotatedFields(...)` and + `findAnnotatedFieldValues(...)` in `AnnotationSupport`. + - See issue link:https://github.com/junit-team/junit5/issues/3638[#3638] for details. +* Method predicates are no longer applied eagerly while searching the type hierarchy. + - This reverts changes made in 5.10.1 that affected `findMethods(...)` and + `streamMethods(...)` in `ReflectionSupport` as well as `findAnnotatedMethods(...)` in + `AnnotationSupport`. + - See issue link:https://github.com/junit-team/junit5/issues/3600[#3600] for details. + + +[[release-notes-5.10.2-junit-jupiter]] +=== JUnit Jupiter + +==== Bug Fixes + +* JUnit Jupiter once again properly detects when a `@Test` method is overridden in a + subclass. + - See issue link:https://github.com/junit-team/junit5/issues/3600[#3600] for details. + +==== Deprecations and Breaking Changes + +* A package-private static field annotated with `@TempDir` is once again _shadowed_ by a + non-static field annotated with `@TempDir` when the non-static field resides in a + different package and has the same name as the static field. + - This reverts changes made in 5.10.1. + - See issue link:https://github.com/junit-team/junit5/issues/3638[#3638] for details. +* A package-private class-level lifecycle method annotated with `@BeforeAll` or + `@AfterAll` is once again _shadowed_ by a method-level lifecycle method annotated with + `@BeforeEach` or `@AfterEach` when the method-level lifecycle method resides in a + different package and has the same name as the class-level lifecycle method. + - This reverts changes made in 5.10.1. + - See issue link:https://github.com/junit-team/junit5/issues/3600[#3600] for details. + + +[[release-notes-5.10.2-junit-vintage]] +=== JUnit Vintage + +No changes. diff --git a/gradle.properties b/gradle.properties index 1521b53da109..a053cb6e220e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,15 +1,13 @@ group = org.junit -version = 5.10.1 +version = 5.10.2 jupiterGroup = org.junit.jupiter platformGroup = org.junit.platform -platformVersion = 1.10.1 +platformVersion = 1.10.2 vintageGroup = org.junit.vintage -vintageVersion = 5.10.1 - -defaultBuiltBy = JUnit Team +vintageVersion = 5.10.2 # We need more metaspace due to apparent memory leak in Asciidoctor/JRuby # The exports are needed due to https://github.com/diffplug/spotless/issues/834 diff --git a/gradle/plugins/build-parameters/build.gradle.kts b/gradle/plugins/build-parameters/build.gradle.kts index f70f2d8bc062..3a1f95263c76 100644 --- a/gradle/plugins/build-parameters/build.gradle.kts +++ b/gradle/plugins/build-parameters/build.gradle.kts @@ -14,20 +14,6 @@ buildParameters { integer("javaToolchainVersion") { description = "Defines the Java toolchain version to use for compiling code" } - group("buildCache") { - string("username") { - description = "Username to authenticate with the remote build cache" - fromEnvironment() - } - string("password") { - description = "Password to authenticate with the remote build cache" - fromEnvironment() - } - string("url") { - description = "URL to the remote build cache" - fromEnvironment() - } - } group("documentation") { description = "Parameters controlling how the documentation is built" bool("replaceCurrentDocs") { @@ -35,26 +21,34 @@ buildParameters { defaultValue = false } } - group("enterprise") { - description = "Parameters controlling Gradle Enterprise features" - group("predictiveTestSelection") { - bool("enabled") { - description = "Whether or not to use Predictive Test Selection for selecting tests to execute" - defaultValue = true - } - } - group("testDistribution") { - bool("enabled") { - description = "Whether or not to use Test Distribution for executing tests" - defaultValue = false - fromEnvironment() + group("junit") { + group("develocity") { + description = "Parameters controlling Develocity features" + group("buildCache") { + string("server") { + description = + "Remote build cache server address (protocol and hostname), e.g. https://eu-build-cache-ge.junit.org" + } } - integer("maxLocalExecutors") { - description = "How many local executors to use for executing tests" - defaultValue = 1 + group("predictiveTestSelection") { + bool("enabled") { + description = "Whether or not to use Predictive Test Selection for selecting tests to execute" + defaultValue = true + } } - integer("maxRemoteExecutors") { - description = "How many remote executors to request for executing tests" + group("testDistribution") { + bool("enabled") { + description = "Whether or not to use Test Distribution for executing tests" + defaultValue = false + fromEnvironment() + } + integer("maxLocalExecutors") { + description = "How many local executors to use for executing tests" + defaultValue = 1 + } + integer("maxRemoteExecutors") { + description = "How many remote executors to request for executing tests" + } } } } @@ -72,4 +66,21 @@ buildParameters { description = "Configures the number of times failing test are retried" } } + group("publishing") { + bool("signArtifacts") { + description = "Sign artifacts before publishing them to Maven repos" + } + } + group("manifest") { + string("buildTimestamp") { + description = "Overrides the value of the 'Build-Date' and 'Build-Time' jar manifest entries. Can be set as a String (e.g. '2023-11-05 17:49:13.996+0100') or as seconds since the epoch." + fromEnvironment("SOURCE_DATE_EPOCH") // see https://reproducible-builds.org/docs/source-date-epoch/ + } + string("builtBy") { + description = "Overrides the value of the 'Built-By' jar manifest entry" + } + string("createdBy") { + description = "Overrides the value of the 'Created-By' jar manifest entry" + } + } } diff --git a/gradle/plugins/common/src/main/kotlin/junitbuild.build-metadata.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.build-metadata.gradle.kts index ad58b4898de5..cdab3f0a509d 100644 --- a/gradle/plugins/common/src/main/kotlin/junitbuild.build-metadata.gradle.kts +++ b/gradle/plugins/common/src/main/kotlin/junitbuild.build-metadata.gradle.kts @@ -2,27 +2,33 @@ import java.time.Instant import java.time.OffsetDateTime import java.time.ZoneOffset import java.time.format.DateTimeFormatter +import java.time.format.DateTimeFormatterBuilder -val buildTimeAndDate = - if (System.getenv().containsKey("SOURCE_DATE_EPOCH")) { - - // SOURCE_DATE_EPOCH is a UNIX timestamp for pinning build metadata against - // in order to achieve reproducible builds - // - // More details - https://reproducible-builds.org/docs/source-date-epoch/ - val sourceDateEpoch = System.getenv("SOURCE_DATE_EPOCH").toLong() +plugins { + id("junitbuild.build-parameters") +} - Instant.ofEpochSecond(sourceDateEpoch).atOffset(ZoneOffset.UTC) +val dateFormatter = DateTimeFormatter.ISO_LOCAL_DATE +val timeFormatter = DateTimeFormatter.ofPattern("HH:mm:ss.SSSZ") - } else { - OffsetDateTime.now() +val buildTimeAndDate = buildParameters.manifest.buildTimestamp + .map { + it.toLongOrNull() + ?.let { s -> Instant.ofEpochSecond(s).atOffset(ZoneOffset.UTC) } + ?: DateTimeFormatterBuilder() + .append(dateFormatter) + .appendLiteral(' ') + .append(timeFormatter) + .toFormatter() + .parse(it) } + .orNull + ?: OffsetDateTime.now() -val buildDate: String by extra { DateTimeFormatter.ISO_LOCAL_DATE.format(buildTimeAndDate) } -val buildTime: String by extra { DateTimeFormatter.ofPattern("HH:mm:ss.SSSZ").format(buildTimeAndDate) } +val buildDate: String by extra { dateFormatter.format(buildTimeAndDate) } +val buildTime: String by extra { timeFormatter.format(buildTimeAndDate) } val buildRevision: String by extra { providers.exec { commandLine("git", "rev-parse", "--verify", "HEAD") }.standardOutput.asText.get() } -val builtByValue by extra { project.findProperty("builtBy") ?: project.property("defaultBuiltBy") } diff --git a/gradle/plugins/common/src/main/kotlin/junitbuild.java-library-conventions.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.java-library-conventions.gradle.kts index 6eb7eb308ec8..4402ec7238a6 100644 --- a/gradle/plugins/common/src/main/kotlin/junitbuild.java-library-conventions.gradle.kts +++ b/gradle/plugins/common/src/main/kotlin/junitbuild.java-library-conventions.gradle.kts @@ -9,6 +9,7 @@ plugins { idea checkstyle id("junitbuild.base-conventions") + id("junitbuild.build-parameters") id("junitbuild.jacoco-java-conventions") } @@ -17,7 +18,6 @@ val modularProjects: List by rootProject.extra val buildDate: String by rootProject.extra val buildTime: String by rootProject.extra val buildRevision: Any by rootProject.extra -val builtByValue: String by rootProject.extra val extension = extensions.create("javaLibrary") @@ -203,8 +203,9 @@ tasks.withType().configureEach { tasks.jar { manifest { attributes( - "Created-By" to "${System.getProperty("java.version")} (${System.getProperty("java.vendor")} ${System.getProperty("java.vm.version")})", - "Built-By" to builtByValue, + "Created-By" to (buildParameters.manifest.createdBy.orNull + ?: "${System.getProperty("java.version")} (${System.getProperty("java.vendor")} ${System.getProperty("java.vm.version")})"), + "Built-By" to buildParameters.manifest.builtBy.orElse("JUnit Team"), "Build-Date" to buildDate, "Build-Time" to buildTime, "Build-Revision" to buildRevision, diff --git a/gradle/plugins/common/src/main/kotlin/junitbuild.publishing-conventions.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.publishing-conventions.gradle.kts index bab950933c2a..ad877035e1f3 100644 --- a/gradle/plugins/common/src/main/kotlin/junitbuild.publishing-conventions.gradle.kts +++ b/gradle/plugins/common/src/main/kotlin/junitbuild.publishing-conventions.gradle.kts @@ -40,17 +40,16 @@ tasks.withType().configureEach { dependsOn(tasks.build) } +val signArtifacts = buildParameters.publishing.signArtifacts.getOrElse(!(isSnapshot || buildParameters.ci)) + signing { useGpgCmd() sign(publishing.publications) - isRequired = !(isSnapshot || buildParameters.ci) + isRequired = signArtifacts } tasks.withType().configureEach { - val isSnapshot = project.version.toString().contains("SNAPSHOT") - onlyIf { - !isSnapshot // Gradle Module Metadata currently does not support signing snapshots - } + enabled = signArtifacts } publishing { diff --git a/gradle/plugins/common/src/main/kotlin/junitbuild.testing-conventions.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.testing-conventions.gradle.kts index 086e1e6135af..9a969dec2369 100644 --- a/gradle/plugins/common/src/main/kotlin/junitbuild.testing-conventions.gradle.kts +++ b/gradle/plugins/common/src/main/kotlin/junitbuild.testing-conventions.gradle.kts @@ -22,9 +22,9 @@ tasks.withType().configureEach { maxRetries = buildParameters.testing.retries.orElse(if (buildParameters.ci) 2 else 0) } distribution { - enabled.convention(buildParameters.enterprise.testDistribution.enabled && (!buildParameters.ci || System.getenv("GRADLE_ENTERPRISE_ACCESS_KEY").isNotBlank())) - maxLocalExecutors = buildParameters.enterprise.testDistribution.maxLocalExecutors - maxRemoteExecutors = buildParameters.enterprise.testDistribution.maxRemoteExecutors + enabled.convention(buildParameters.junit.develocity.testDistribution.enabled && (!buildParameters.ci || System.getenv("GRADLE_ENTERPRISE_ACCESS_KEY").isNotBlank())) + maxLocalExecutors = buildParameters.junit.develocity.testDistribution.maxLocalExecutors + maxRemoteExecutors = buildParameters.junit.develocity.testDistribution.maxRemoteExecutors if (buildParameters.ci) { when { OperatingSystem.current().isLinux -> requirements.add("os=linux") @@ -34,7 +34,7 @@ tasks.withType().configureEach { } } predictiveSelection { - enabled = buildParameters.enterprise.predictiveTestSelection.enabled + enabled = buildParameters.junit.develocity.predictiveTestSelection.enabled // Ensure PTS works when publishing Build Scans to scans.gradle.com this as PredictiveTestSelectionExtensionInternal diff --git a/gradle/scripts/checkBuildReproducibility.sh b/gradle/scripts/checkBuildReproducibility.sh index b07275624da1..c434fc778a44 100755 --- a/gradle/scripts/checkBuildReproducibility.sh +++ b/gradle/scripts/checkBuildReproducibility.sh @@ -7,13 +7,19 @@ export SOURCE_DATE_EPOCH=$(date +%s) function calculate_checksums() { OUTPUT=$1 - ./gradlew --no-build-cache clean assemble --parallel -Porg.gradle.java.installations.auto-download=false -Dscan.tag.Reproducibility + ./gradlew \ + --configuration-cache \ + --no-build-cache \ + -Porg.gradle.java.installations.auto-download=false \ + -Dscan.tag.Reproducibility \ + clean \ + assemble find . -name '*.jar' \ | grep '/build/libs/' \ | grep --invert-match 'javadoc' \ | sort \ - | xargs sha256sum > ${OUTPUT} + | xargs sha256sum > "${OUTPUT}" } 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 478b3372add0..7994ceff65a7 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 @@ -1253,23 +1253,21 @@ public static Stream streamFields(Class clazz, Predicate predic Preconditions.notNull(predicate, "Predicate must not be null"); Preconditions.notNull(traversalMode, "HierarchyTraversalMode must not be null"); - return findAllFieldsInHierarchy(clazz, predicate, traversalMode).stream(); + return findAllFieldsInHierarchy(clazz, traversalMode).stream().filter(predicate); } - private static List findAllFieldsInHierarchy(Class clazz, Predicate predicate, - HierarchyTraversalMode traversalMode) { - + private static List findAllFieldsInHierarchy(Class clazz, HierarchyTraversalMode traversalMode) { Preconditions.notNull(clazz, "Class must not be null"); Preconditions.notNull(traversalMode, "HierarchyTraversalMode must not be null"); // @formatter:off - List localFields = getDeclaredFields(clazz, predicate).stream() + List localFields = getDeclaredFields(clazz).stream() .filter(field -> !field.isSynthetic()) .collect(toList()); - List superclassFields = getSuperclassFields(clazz, predicate, traversalMode).stream() + List superclassFields = getSuperclassFields(clazz, traversalMode).stream() .filter(field -> !isFieldShadowedByLocalFields(field, localFields)) .collect(toList()); - List interfaceFields = getInterfaceFields(clazz, predicate, traversalMode).stream() + List interfaceFields = getInterfaceFields(clazz, traversalMode).stream() .filter(field -> !isFieldShadowedByLocalFields(field, localFields)) .collect(toList()); // @formatter:on @@ -1407,11 +1405,11 @@ private static Optional findMethod(Class clazz, Predicate pre for (Class current = clazz; isSearchable(current); current = current.getSuperclass()) { // Search for match in current type - List methods = current.isInterface() ? getMethods(current, predicate) - : getDeclaredMethods(current, predicate, BOTTOM_UP); - if (!methods.isEmpty()) { - // Since the predicate has already been applied, return the first match. - return Optional.of(methods.get(0)); + List methods = current.isInterface() ? getMethods(current) : getDeclaredMethods(current, BOTTOM_UP); + for (Method method : methods) { + if (predicate.test(method)) { + return Optional.of(method); + } } // Search for match in interfaces implemented by current type @@ -1492,27 +1490,29 @@ public static Stream streamMethods(Class clazz, Predicate pre Preconditions.notNull(predicate, "Predicate must not be null"); Preconditions.notNull(traversalMode, "HierarchyTraversalMode must not be null"); - return findAllMethodsInHierarchy(clazz, predicate, traversalMode).stream().distinct(); + // @formatter:off + return findAllMethodsInHierarchy(clazz, traversalMode).stream() + .filter(predicate) + .distinct(); + // @formatter:on } /** * Find all non-synthetic methods in the superclass and interface hierarchy, - * excluding Object, that match the specified {@code predicate}. + * excluding Object. */ - private static List findAllMethodsInHierarchy(Class clazz, Predicate predicate, - HierarchyTraversalMode traversalMode) { - + private static List findAllMethodsInHierarchy(Class clazz, HierarchyTraversalMode traversalMode) { Preconditions.notNull(clazz, "Class must not be null"); Preconditions.notNull(traversalMode, "HierarchyTraversalMode must not be null"); // @formatter:off - List localMethods = getDeclaredMethods(clazz, predicate, traversalMode).stream() + List localMethods = getDeclaredMethods(clazz, traversalMode).stream() .filter(method -> !method.isSynthetic()) .collect(toList()); - List superclassMethods = getSuperclassMethods(clazz, predicate, traversalMode).stream() + List superclassMethods = getSuperclassMethods(clazz, traversalMode).stream() .filter(method -> !isMethodShadowedByLocalMethods(method, localMethods)) .collect(toList()); - List interfaceMethods = getInterfaceMethods(clazz, predicate, traversalMode).stream() + List interfaceMethods = getInterfaceMethods(clazz, traversalMode).stream() .filter(method -> !isMethodShadowedByLocalMethods(method, localMethods)) .collect(toList()); // @formatter:on @@ -1532,42 +1532,40 @@ private static List findAllMethodsInHierarchy(Class clazz, Predicate< /** * Custom alternative to {@link Class#getFields()} that sorts the fields - * which match the supplied predicate and converts them to a mutable list. + * and converts them to a mutable list. */ - private static List getFields(Class clazz, Predicate predicate) { - return toSortedMutableList(clazz.getFields(), predicate); + private static List getFields(Class clazz) { + return toSortedMutableList(clazz.getFields()); } /** * Custom alternative to {@link Class#getDeclaredFields()} that sorts the - * fields which match the supplied predicate and converts them to a mutable list. + * fields and converts them to a mutable list. */ - private static List getDeclaredFields(Class clazz, Predicate predicate) { - return toSortedMutableList(clazz.getDeclaredFields(), predicate); + private static List getDeclaredFields(Class clazz) { + return toSortedMutableList(clazz.getDeclaredFields()); } /** * Custom alternative to {@link Class#getMethods()} that sorts the methods - * which match the supplied predicate and converts them to a mutable list. + * and converts them to a mutable list. */ - private static List getMethods(Class clazz, Predicate predicate) { - return toSortedMutableList(clazz.getMethods(), predicate); + private static List getMethods(Class clazz) { + return toSortedMutableList(clazz.getMethods()); } /** * Custom alternative to {@link Class#getDeclaredMethods()} that sorts the - * methods which match the supplied predicate and converts them to a mutable list. + * methods and converts them to a mutable list. * *

In addition, the list returned by this method includes interface * default methods which are either prepended or appended to the list of * declared methods depending on the supplied traversal mode. */ - private static List getDeclaredMethods(Class clazz, Predicate predicate, - HierarchyTraversalMode traversalMode) { - + private static List getDeclaredMethods(Class clazz, HierarchyTraversalMode traversalMode) { // Note: getDefaultMethods() already sorts the methods, - List defaultMethods = getDefaultMethods(clazz, predicate); - List declaredMethods = toSortedMutableList(clazz.getDeclaredMethods(), predicate); + List defaultMethods = getDefaultMethods(clazz); + List declaredMethods = toSortedMutableList(clazz.getDeclaredMethods()); // Take the traversal mode into account in order to retain the inherited // nature of interface default methods. @@ -1584,43 +1582,41 @@ private static List getDeclaredMethods(Class clazz, Predicate /** * Get a sorted, mutable list of all default methods present in interfaces * implemented by the supplied class which are also visible within - * the supplied class and match the supplied predicate. + * the supplied class. * * @see Method Visibility * in the Java Language Specification */ - private static List getDefaultMethods(Class clazz, Predicate predicate) { + private static List getDefaultMethods(Class clazz) { // @formatter:off // Visible default methods are interface default methods that have not // been overridden. List visibleDefaultMethods = Arrays.stream(clazz.getMethods()) - .filter(predicate.and(Method::isDefault)) + .filter(Method::isDefault) .collect(toCollection(ArrayList::new)); if (visibleDefaultMethods.isEmpty()) { return visibleDefaultMethods; } return Arrays.stream(clazz.getInterfaces()) - .map(ifc -> getMethods(ifc, predicate)) + .map(ReflectionUtils::getMethods) .flatMap(List::stream) .filter(visibleDefaultMethods::contains) .collect(toCollection(ArrayList::new)); // @formatter:on } - private static List toSortedMutableList(Field[] fields, Predicate predicate) { + private static List toSortedMutableList(Field[] fields) { // @formatter:off return Arrays.stream(fields) - .filter(predicate) .sorted(ReflectionUtils::defaultFieldSorter) // Use toCollection() instead of toList() to ensure list is mutable. .collect(toCollection(ArrayList::new)); // @formatter:on } - private static List toSortedMutableList(Method[] methods, Predicate predicate) { + private static List toSortedMutableList(Method[] methods) { // @formatter:off return Arrays.stream(methods) - .filter(predicate) .sorted(ReflectionUtils::defaultMethodSorter) // Use toCollection() instead of toList() to ensure list is mutable. .collect(toCollection(ArrayList::new)); @@ -1652,18 +1648,16 @@ private static int defaultMethodSorter(Method method1, Method method2) { return comparison; } - private static List getInterfaceMethods(Class clazz, Predicate predicate, - HierarchyTraversalMode traversalMode) { - + private static List getInterfaceMethods(Class clazz, HierarchyTraversalMode traversalMode) { List allInterfaceMethods = new ArrayList<>(); for (Class ifc : clazz.getInterfaces()) { // @formatter:off - List localInterfaceMethods = getMethods(ifc, predicate).stream() - .filter(method -> !isAbstract(method)) + List localInterfaceMethods = getMethods(ifc).stream() + .filter(m -> !isAbstract(m)) .collect(toList()); - List superinterfaceMethods = getInterfaceMethods(ifc, predicate, traversalMode).stream() + List superinterfaceMethods = getInterfaceMethods(ifc, traversalMode).stream() .filter(method -> !isMethodShadowedByLocalMethods(method, localInterfaceMethods)) .collect(toList()); // @formatter:on @@ -1679,15 +1673,13 @@ private static List getInterfaceMethods(Class clazz, Predicate getInterfaceFields(Class clazz, Predicate predicate, - HierarchyTraversalMode traversalMode) { - + private static List getInterfaceFields(Class clazz, HierarchyTraversalMode traversalMode) { List allInterfaceFields = new ArrayList<>(); for (Class ifc : clazz.getInterfaces()) { - List localInterfaceFields = getFields(ifc, predicate); + List localInterfaceFields = getFields(ifc); // @formatter:off - List superinterfaceFields = getInterfaceFields(ifc, predicate, traversalMode).stream() + List superinterfaceFields = getInterfaceFields(ifc, traversalMode).stream() .filter(field -> !isFieldShadowedByLocalFields(field, localInterfaceFields)) .collect(toList()); // @formatter:on @@ -1703,28 +1695,24 @@ private static List getInterfaceFields(Class clazz, Predicate p return allInterfaceFields; } - private static List getSuperclassFields(Class clazz, Predicate predicate, - HierarchyTraversalMode traversalMode) { - + private static List getSuperclassFields(Class clazz, HierarchyTraversalMode traversalMode) { Class superclass = clazz.getSuperclass(); if (!isSearchable(superclass)) { return Collections.emptyList(); } - return findAllFieldsInHierarchy(superclass, predicate, traversalMode); + return findAllFieldsInHierarchy(superclass, traversalMode); } private static boolean isFieldShadowedByLocalFields(Field field, List localFields) { return localFields.stream().anyMatch(local -> local.getName().equals(field.getName())); } - private static List getSuperclassMethods(Class clazz, Predicate predicate, - HierarchyTraversalMode traversalMode) { - + private static List getSuperclassMethods(Class clazz, HierarchyTraversalMode traversalMode) { Class superclass = clazz.getSuperclass(); if (!isSearchable(superclass)) { return Collections.emptyList(); } - return findAllMethodsInHierarchy(superclass, predicate, traversalMode); + return findAllMethodsInHierarchy(superclass, traversalMode); } private static boolean isMethodShadowedByLocalMethods(Method method, List localMethods) { diff --git a/junit-platform-launcher/src/module/org.junit.platform.launcher/module-info.java b/junit-platform-launcher/src/module/org.junit.platform.launcher/module-info.java index 9501caff5a6a..9d79f3f4166a 100644 --- a/junit-platform-launcher/src/module/org.junit.platform.launcher/module-info.java +++ b/junit-platform-launcher/src/module/org.junit.platform.launcher/module-info.java @@ -16,6 +16,8 @@ * @since 1.0 * @uses org.junit.platform.engine.TestEngine * @uses org.junit.platform.launcher.LauncherDiscoveryListener + * @uses org.junit.platform.launcher.LauncherInterceptor + * @uses org.junit.platform.launcher.LauncherSessionListener * @uses org.junit.platform.launcher.PostDiscoveryFilter * @uses org.junit.platform.launcher.TestExecutionListener */ @@ -32,6 +34,7 @@ uses org.junit.platform.engine.TestEngine; uses org.junit.platform.launcher.LauncherDiscoveryListener; + uses org.junit.platform.launcher.LauncherInterceptor; uses org.junit.platform.launcher.LauncherSessionListener; uses org.junit.platform.launcher.PostDiscoveryFilter; uses org.junit.platform.launcher.TestExecutionListener; diff --git a/platform-tests/src/test/java/org/junit/platform/commons/util/AnnotationUtilsTests.java b/platform-tests/src/test/java/org/junit/platform/commons/util/AnnotationUtilsTests.java index 5dde2c34cbd9..ec9959c553f0 100644 --- a/platform-tests/src/test/java/org/junit/platform/commons/util/AnnotationUtilsTests.java +++ b/platform-tests/src/test/java/org/junit/platform/commons/util/AnnotationUtilsTests.java @@ -44,6 +44,7 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.pkg1.ClassLevelDir; @@ -390,10 +391,11 @@ void findAnnotatedMethodsForAnnotationUsedInClassAndSuperclassHierarchyDown() th } /** - * @see https://github.com/junit-team/junit5/issues/3498 + * @see https://github.com/junit-team/junit5/issues/3553 */ + @Disabled("Until #3553 is resolved") @Test - void findAnnotatedMethodsAppliesPredicateBeforeSearchingTypeHierarchy() throws Exception { + void findAnnotatedMethodsDoesNotAllowInstanceMethodToHideStaticMethod() throws Exception { final String BEFORE = "before"; Class superclass = SuperclassWithStaticPackagePrivateBeforeMethod.class; Method beforeAllMethod = superclass.getDeclaredMethod(BEFORE); @@ -509,10 +511,11 @@ private List findShadowingAnnotatedFields(Class ann } /** - * @see https://github.com/junit-team/junit5/issues/3532 + * @see https://github.com/junit-team/junit5/issues/3553 */ + @Disabled("Until #3553 is resolved") @Test - void findAnnotatedFieldsAppliesPredicateBeforeSearchingTypeHierarchy() throws Exception { + void findAnnotatedFieldsDoesNotAllowInstanceFieldToHideStaticField() throws Exception { final String TEMP_DIR = "tempDir"; Class superclass = SuperclassWithStaticPackagePrivateTempDirField.class; Field staticField = superclass.getDeclaredField(TEMP_DIR); diff --git a/platform-tests/src/test/java/org/junit/platform/commons/util/ReflectionUtilsTests.java b/platform-tests/src/test/java/org/junit/platform/commons/util/ReflectionUtilsTests.java index 7cccbe13a70c..24f54828aca6 100644 --- a/platform-tests/src/test/java/org/junit/platform/commons/util/ReflectionUtilsTests.java +++ b/platform-tests/src/test/java/org/junit/platform/commons/util/ReflectionUtilsTests.java @@ -52,6 +52,7 @@ import java.util.stream.IntStream; import java.util.stream.Stream; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.fixtures.TrackLogRecords; @@ -1351,10 +1352,11 @@ void findMethodsIgnoresBridgeMethods() throws Exception { } /** - * @see https://github.com/junit-team/junit5/issues/3498 + * @see https://github.com/junit-team/junit5/issues/3553 */ + @Disabled("Until #3553 is resolved") @Test - void findMethodsAppliesPredicateBeforeSearchingTypeHierarchy() throws Exception { + void findMethodsDoesNotAllowInstanceMethodToHideStaticMethod() throws Exception { final String BEFORE = "before"; Class superclass = SuperclassWithStaticPackagePrivateBeforeMethod.class; Method staticMethod = superclass.getDeclaredMethod(BEFORE); @@ -1383,10 +1385,11 @@ void isGeneric() { } /** - * @see https://github.com/junit-team/junit5/issues/3532 + * @see https://github.com/junit-team/junit5/issues/3553 */ + @Disabled("Until #3553 is resolved") @Test - void findFieldsAppliesPredicateBeforeSearchingTypeHierarchy() throws Exception { + void findFieldsDoesNotAllowInstanceFieldToHideStaticField() throws Exception { final String TEMP_DIR = "tempDir"; Class superclass = SuperclassWithStaticPackagePrivateTempDirField.class; Field staticField = superclass.getDeclaredField(TEMP_DIR); diff --git a/platform-tests/src/test/java/org/junit/platform/commons/util/pkg1/SuperclassWithStaticPackagePrivateBeforeMethod.java b/platform-tests/src/test/java/org/junit/platform/commons/util/pkg1/SuperclassWithStaticPackagePrivateBeforeMethod.java index 2895f2b4980d..3b5a2333d413 100644 --- a/platform-tests/src/test/java/org/junit/platform/commons/util/pkg1/SuperclassWithStaticPackagePrivateBeforeMethod.java +++ b/platform-tests/src/test/java/org/junit/platform/commons/util/pkg1/SuperclassWithStaticPackagePrivateBeforeMethod.java @@ -13,7 +13,7 @@ import org.junit.jupiter.api.BeforeAll; /** - * @see https://github.com/junit-team/junit5/issues/3498 + * @see https://github.com/junit-team/junit5/issues/3553 */ public class SuperclassWithStaticPackagePrivateBeforeMethod { diff --git a/platform-tests/src/test/java/org/junit/platform/commons/util/pkg1/SuperclassWithStaticPackagePrivateTempDirField.java b/platform-tests/src/test/java/org/junit/platform/commons/util/pkg1/SuperclassWithStaticPackagePrivateTempDirField.java index 4e2bbe7ec696..f091bddc35a5 100644 --- a/platform-tests/src/test/java/org/junit/platform/commons/util/pkg1/SuperclassWithStaticPackagePrivateTempDirField.java +++ b/platform-tests/src/test/java/org/junit/platform/commons/util/pkg1/SuperclassWithStaticPackagePrivateTempDirField.java @@ -13,7 +13,7 @@ import java.nio.file.Path; /** - * @see https://github.com/junit-team/junit5/issues/3532 + * @see https://github.com/junit-team/junit5/issues/3553 */ public class SuperclassWithStaticPackagePrivateTempDirField { diff --git a/platform-tests/src/test/java/org/junit/platform/commons/util/pkg1/subpkg/SubclassWithNonStaticPackagePrivateBeforeMethod.java b/platform-tests/src/test/java/org/junit/platform/commons/util/pkg1/subpkg/SubclassWithNonStaticPackagePrivateBeforeMethod.java index c7c6d1e0ac22..6ce5bfb4ff75 100644 --- a/platform-tests/src/test/java/org/junit/platform/commons/util/pkg1/subpkg/SubclassWithNonStaticPackagePrivateBeforeMethod.java +++ b/platform-tests/src/test/java/org/junit/platform/commons/util/pkg1/subpkg/SubclassWithNonStaticPackagePrivateBeforeMethod.java @@ -14,7 +14,7 @@ import org.junit.platform.commons.util.pkg1.SuperclassWithStaticPackagePrivateBeforeMethod; /** - * @see https://github.com/junit-team/junit5/issues/3498 + * @see https://github.com/junit-team/junit5/issues/3553 */ public class SubclassWithNonStaticPackagePrivateBeforeMethod extends SuperclassWithStaticPackagePrivateBeforeMethod { diff --git a/platform-tests/src/test/java/org/junit/platform/commons/util/pkg1/subpkg/SubclassWithNonStaticPackagePrivateTempDirField.java b/platform-tests/src/test/java/org/junit/platform/commons/util/pkg1/subpkg/SubclassWithNonStaticPackagePrivateTempDirField.java index d7eb33f6a326..83504ecab639 100644 --- a/platform-tests/src/test/java/org/junit/platform/commons/util/pkg1/subpkg/SubclassWithNonStaticPackagePrivateTempDirField.java +++ b/platform-tests/src/test/java/org/junit/platform/commons/util/pkg1/subpkg/SubclassWithNonStaticPackagePrivateTempDirField.java @@ -16,7 +16,7 @@ import org.junit.platform.commons.util.pkg1.SuperclassWithStaticPackagePrivateTempDirField; /** - * @see https://github.com/junit-team/junit5/issues/3532 + * @see https://github.com/junit-team/junit5/issues/3553 */ public class SubclassWithNonStaticPackagePrivateTempDirField extends SuperclassWithStaticPackagePrivateTempDirField { diff --git a/platform-tests/src/test/java/org/junit/platform/reporting/open/xml/OpenTestReportGeneratingListenerTests.java b/platform-tests/src/test/java/org/junit/platform/reporting/open/xml/OpenTestReportGeneratingListenerTests.java index 99398dbc31e8..e0abc5fd55e5 100644 --- a/platform-tests/src/test/java/org/junit/platform/reporting/open/xml/OpenTestReportGeneratingListenerTests.java +++ b/platform-tests/src/test/java/org/junit/platform/reporting/open/xml/OpenTestReportGeneratingListenerTests.java @@ -13,6 +13,7 @@ import static java.util.Objects.requireNonNull; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.fail; +import static org.junit.jupiter.api.condition.JRE.JAVA_22; import static org.junit.jupiter.api.io.CleanupMode.ON_SUCCESS; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectUniqueId; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; @@ -26,6 +27,7 @@ import java.nio.file.Path; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.DisabledForJreRange; import org.junit.jupiter.api.io.TempDir; import org.junit.platform.engine.TestEngine; import org.junit.platform.engine.UniqueId; @@ -41,6 +43,7 @@ * * @since 1.9 */ +@DisabledForJreRange(min = JAVA_22, disabledReason = "https://github.com/junit-team/junit5/issues/3594") public class OpenTestReportGeneratingListenerTests { @TempDir(cleanup = ON_SUCCESS) diff --git a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-launcher.expected.txt b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-launcher.expected.txt index 1461169b0fee..41bb2afac024 100644 --- a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-launcher.expected.txt +++ b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-launcher.expected.txt @@ -10,6 +10,7 @@ requires org.junit.platform.commons transitive requires org.junit.platform.engine transitive uses org.junit.platform.engine.TestEngine uses org.junit.platform.launcher.LauncherDiscoveryListener +uses org.junit.platform.launcher.LauncherInterceptor uses org.junit.platform.launcher.LauncherSessionListener uses org.junit.platform.launcher.PostDiscoveryFilter uses org.junit.platform.launcher.TestExecutionListener diff --git a/settings.gradle.kts b/settings.gradle.kts index 8ae205fbcbeb..9c9c22a202e6 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -25,18 +25,20 @@ dependencyResolutionManagement { } val buildParameters = the() -val gradleEnterpriseServer = "https://ge.junit.org" +val develocityServer = "https://ge.junit.org" +val useDevelocityInstance = !gradle.startParameter.isBuildScan gradleEnterprise { + if (useDevelocityInstance) { + // Publish to scans.gradle.com when `--scan` is used explicitly + server = develocityServer + } buildScan { capture.isTaskInputFiles = true isUploadInBackground = !buildParameters.ci - publishAlways() - - // Publish to scans.gradle.com when `--scan` is used explicitly - if (!gradle.startParameter.isBuildScan) { - server = gradleEnterpriseServer + if (useDevelocityInstance) { + publishAlways() this as BuildScanExtensionWithHiddenFeatures publishIfAuthenticated() } @@ -50,7 +52,7 @@ gradleEnterprise { } } - if (buildParameters.enterprise.testDistribution.enabled) { + if (buildParameters.junit.develocity.testDistribution.enabled) { tag("test-distribution") } } @@ -60,14 +62,16 @@ buildCache { local { isEnabled = !buildParameters.ci } - remote { - url = uri(buildParameters.buildCache.url.getOrElse("$gradleEnterpriseServer/cache/")) - val buildCacheUsername = buildParameters.buildCache.username.orNull?.ifBlank { null } - val buildCachePassword = buildParameters.buildCache.password.orNull?.ifBlank { null } - isPush = buildParameters.ci && buildCacheUsername != null && buildCachePassword != null - credentials { - username = buildCacheUsername - password = buildCachePassword + val buildCacheServer = buildParameters.junit.develocity.buildCache.server + if (useDevelocityInstance) { + remote(gradleEnterprise.buildCache) { + server = buildCacheServer.orNull + val authenticated = System.getenv("GRADLE_ENTERPRISE_ACCESS_KEY") != null + isPush = buildParameters.ci && authenticated + } + } else { + remote { + url = uri(buildCacheServer.getOrElse(develocityServer)).resolve("/cache/") } } }